Browse code

sctp: cleanup

sctp_init_sock() broken into several functions (sctp_init_su,
sctp_init_sock_opt_common, sctp_bind_sock), to allow for code reuse
with a future sctp one-to-one implementation.

Andrei Pelinescu-Onciul authored on 01/10/2008 17:30:57
Showing 1 changed files
... ...
@@ -52,18 +52,16 @@
52 52
 
53 53
 
54 54
 
55
-int sctp_init_sock(struct socket_info* sock_info)
55
+/* init all the sockaddr_union members of the socket_info struct
56
+   returns 0 on success and -1 on error */
57
+inline static int sctp_init_su(struct socket_info* sock_info)
56 58
 {
57 59
 	union sockaddr_union* addr;
58
-	int optval;
59
-	socklen_t optlen;
60 60
 	struct addr_info* ai;
61
-	struct sctp_event_subscribe es;
62 61
 	
63 62
 	addr=&sock_info->su;
64
-	sock_info->proto=PROTO_SCTP;
65 63
 	if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
66
-		LOG(L_ERR, "ERROR: sctp_init_sock: could not init sockaddr_union for"
64
+		LOG(L_ERR, "ERROR: sctp_init_su: could not init sockaddr_union for"
67 65
 					"primary sctp address %.*s:%d\n",
68 66
 					sock_info->address_str.len, sock_info->address_str.s,
69 67
 					sock_info->port_no );
... ...
@@ -71,44 +69,34 @@ int sctp_init_sock(struct socket_info* sock_info)
71 71
 	}
72 72
 	for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
73 73
 		if (init_su(&ai->su, &ai->address, sock_info->port_no)<0){
74
-			LOG(L_ERR, "ERROR: sctp_init_sock: could not init"
74
+			LOG(L_ERR, "ERROR: sctp_init_su: could not init"
75 75
 					"backup sctp sockaddr_union for %.*s:%d\n",
76 76
 					ai->address_str.len, ai->address_str.s,
77 77
 					sock_info->port_no );
78 78
 			goto error;
79 79
 		}
80
-	sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_SEQPACKET, 
81
-								IPPROTO_SCTP);
82
-	if (sock_info->socket==-1){
83
-		LOG(L_ERR, "ERROR: sctp_init_sock: socket: %s\n", strerror(errno));
84
-		goto error;
85
-	}
86
-	INFO("sctp: socket %d initialized (%p)\n", sock_info->socket, sock_info);
87
-	/* make socket non-blocking */
88
-#if 0
89
-	/* recvmsg must block so use blocking sockets
90
-	 * and send with MSG_DONTWAIT */
91
-	optval=fcntl(sock_info->socket, F_GETFL);
92
-	if (optval==-1){
93
-		LOG(L_ERR, "ERROR: init_sctp: fnctl failed: (%d) %s\n",
94
-				errno, strerror(errno));
95
-		goto error;
96
-	}
97
-	if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
98
-		LOG(L_ERR, "ERROR: init_sctp: fcntl: set non-blocking failed:"
99
-				" (%d) %s\n", errno, strerror(errno));
100
-		goto error;
101
-	}
102
-#endif
80
+	return 0;
81
+error:
82
+	return -1;
83
+}
103 84
 
104
-	/* set sock opts */
85
+
86
+
87
+/* set common (for one to many and one to one) sctp socket options
88
+   returns 0 on success, -1 on error */
89
+static int sctp_init_sock_opt_common(int s)
90
+{
91
+	struct sctp_event_subscribe es;
92
+	int optval;
93
+	socklen_t optlen;
94
+	
105 95
 	/* set receive buffer: SO_RCVBUF*/
106 96
 	if (sctp_options.sctp_so_rcvbuf){
107 97
 		optval=sctp_options.sctp_so_rcvbuf;
108
-		if (setsockopt(sock_info->socket, SOL_SOCKET, SO_RCVBUF,
98
+		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
109 99
 					(void*)&optval, sizeof(optval)) ==-1){
110
-			LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: SO_RCVBUF (%d):"
111
-						" %s\n", optval, strerror(errno));
100
+			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
101
+						" SO_RCVBUF (%d): %s\n", optval, strerror(errno));
112 102
 			/* continue, non-critical */
113 103
 		}
114 104
 	}
... ...
@@ -116,10 +104,10 @@ int sctp_init_sock(struct socket_info* sock_info)
116 116
 	/* set send buffer: SO_SNDBUF */
117 117
 	if (sctp_options.sctp_so_sndbuf){
118 118
 		optval=sctp_options.sctp_so_sndbuf;
119
-		if (setsockopt(sock_info->socket, SOL_SOCKET, SO_SNDBUF,
119
+		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
120 120
 					(void*)&optval, sizeof(optval)) ==-1){
121
-			LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: SO_SNDBUF (%d):"
122
-						" %s\n", optval, strerror(errno));
121
+			LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt:"
122
+						" SO_SNDBUF (%d): %s\n", optval, strerror(errno));
123 123
 			/* continue, non-critical */
124 124
 		}
125 125
 	}
... ...
@@ -128,10 +116,10 @@ int sctp_init_sock(struct socket_info* sock_info)
128 128
 	 * we don't want partial delivery, so fragment interleave must be off too
129 129
 	 */
130 130
 	optval=0;
131
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE ,
131
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE ,
132 132
 					(void*)&optval, sizeof(optval)) ==-1){
133
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: %s\n",
134
-						strerror(errno));
133
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
134
+					"SCTP_FRAGMENT_INTERLEAVE: %s\n", strerror(errno));
135 135
 		goto error;
136 136
 	}
137 137
 	
... ...
@@ -140,43 +128,44 @@ int sctp_init_sock(struct socket_info* sock_info)
140 140
 	 * way to do it is to set it to the socket receive buffer size
141 141
 	 * (this is the maximum value allowed in the sctp api draft) */
142 142
 	optlen=sizeof(optval);
143
-	if (getsockopt(sock_info->socket, SOL_SOCKET, SO_RCVBUF,
143
+	if (getsockopt(s, SOL_SOCKET, SO_RCVBUF,
144 144
 					(void*)&optval, &optlen) ==-1){
145
-		LOG(L_ERR, "ERROR: sctp_init_sock: getsockopt: %s\n",
146
-						strerror(errno));
145
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: getsockopt: "
146
+						"SO_RCVBUF: %s\n", strerror(errno));
147 147
 		goto error;
148 148
 	}
149
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
149
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
150 150
 					(void*)&optval, sizeof(optval)) ==-1){
151
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: %s\n",
152
-						strerror(errno));
151
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
152
+						"SCTP_PARTIAL_DELIVERY_POINT (%d): %s\n",
153
+						optval, strerror(errno));
153 154
 		goto error;
154 155
 	}
155 156
 	
156 157
 	/* nagle / no delay */
157 158
 	optval=1;
158
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_NODELAY,
159
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY,
159 160
 					(void*)&optval, sizeof(optval)) ==-1){
160
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: %s\n",
161
-						strerror(errno));
161
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
162
+						"SCTP_NODELAY: %s\n", strerror(errno));
162 163
 		/* non critical, try to continue */
163 164
 	}
164 165
 	
165 166
 	/* enable message fragmentation (SCTP_DISABLE_FRAGMENTS)  (on send) */
166 167
 	optval=0;
167
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
168
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
168 169
 					(void*)&optval, sizeof(optval)) ==-1){
169
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: %s\n",
170
-						strerror(errno));
170
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
171
+						"SCTP_DISABLE_FRAGMENTS: %s\n", strerror(errno));
171 172
 		/* non critical, try to continue */
172 173
 	}
173 174
 	
174 175
 	/* set autoclose */
175 176
 	optval=sctp_options.sctp_autoclose;
176
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
177
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS,
177 178
 					(void*)&optval, sizeof(optval)) ==-1){
178
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: %s\n",
179
-						strerror(errno));
179
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
180
+						"SCTP_DISABLE_FRAGMENTS: %s\n", strerror(errno));
180 181
 		/* non critical, try to continue */
181 182
 	}
182 183
 	
... ...
@@ -195,29 +184,37 @@ int sctp_init_sock(struct socket_info* sock_info)
195 195
 	/* es.sctp_authentication_event=1; -- not supported on linux 2.6.25 */
196 196
 	
197 197
 	/* enable the SCTP_EVENTS */
198
-	if (setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_EVENTS,
199
-						&es, sizeof(es))==-1){
200
-		LOG(L_ERR, "ERROR: sctp_init_sock: setsockopt: SCTP_EVENTS: %s\n",
201
-						strerror(errno));
198
+	if (setsockopt(s, IPPROTO_SCTP, SCTP_EVENTS, &es, sizeof(es))==-1){
199
+		LOG(L_ERR, "ERROR: sctp_init_sock_opt_common: setsockopt: "
200
+				"SCTP_EVENTS: %s\n", strerror(errno));
202 201
 		/* non critical, try to continue */
203 202
 	}
204 203
 	
205
-	/* SCTP_EVENTS for send dried out -> present in the draft not yet
206
-	 * present in linux (might help to detect when we could send again to
207
-	 * some peer, kind of poor's man poll on write, based on received
208
-	 * SCTP_SENDER_DRY_EVENTs */
209
-	
204
+	return 0;
205
+error:
206
+	return -1;
207
+}
208
+
209
+
210
+
211
+/* bind all addresses from sock (sockaddr_unions)
212
+   returns 0 on success, .1 on error */
213
+static int sctp_bind_sock(struct socket_info* sock_info)
214
+{
215
+	struct addr_info* ai;
216
+	union sockaddr_union* addr;
210 217
 	
211
-	/* bind the addresses  (TODO multiple addresses support)*/
218
+	addr=&sock_info->su;
219
+	/* bind the addresses*/
212 220
 	if (bind(sock_info->socket,  &addr->s, sockaddru_len(*addr))==-1){
213
-		LOG(L_ERR, "ERROR: sctp_init_sock: bind(%x, %p, %d) on %s: %s\n",
221
+		LOG(L_ERR, "ERROR: sctp_bind_sock: bind(%x, %p, %d) on %s: %s\n",
214 222
 				sock_info->socket, &addr->s, 
215 223
 				(unsigned)sockaddru_len(*addr),
216 224
 				sock_info->address_str.s,
217 225
 				strerror(errno));
218 226
 	#ifdef USE_IPV6
219 227
 		if (addr->s.sa_family==AF_INET6)
220
-			LOG(L_ERR, "ERROR: sctp_init_sock: might be caused by using a "
228
+			LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
221 229
 							"link local address, try site local or global\n");
222 230
 	#endif
223 231
 		goto error;
... ...
@@ -225,7 +222,7 @@ int sctp_init_sock(struct socket_info* sock_info)
225 225
 	for (ai=sock_info->addr_info_lst; ai; ai=ai->next)
226 226
 		if (sctp_bindx(sock_info->socket, &ai->su.s, 1, SCTP_BINDX_ADD_ADDR)
227 227
 					==-1){
228
-			LOG(L_ERR, "ERROR: sctp_init_sock: sctp_bindx(%x, %.*s:%d, 1, ...)"
228
+			LOG(L_ERR, "ERROR: sctp_bind_sock: sctp_bindx(%x, %.*s:%d, 1, ...)"
229 229
 						" on %s:%d : [%d] %s (trying to continue)\n",
230 230
 						sock_info->socket,
231 231
 						ai->address_str.len, ai->address_str.s, 
... ...
@@ -234,12 +231,63 @@ int sctp_init_sock(struct socket_info* sock_info)
234 234
 						errno, strerror(errno));
235 235
 		#ifdef USE_IPV6
236 236
 			if (ai->su.s.sa_family==AF_INET6)
237
-				LOG(L_ERR, "ERROR: sctp_init_sock: might be caused by using a "
237
+				LOG(L_ERR, "ERROR: sctp_bind_sock: might be caused by using a "
238 238
 							"link local address, try site local or global\n");
239 239
 		#endif
240 240
 			/* try to continue, a secondary address bind failure is not 
241 241
 			 * critical */
242 242
 		}
243
+	return 0;
244
+error:
245
+	return -1;
246
+}
247
+
248
+
249
+
250
+/* init, bind & start listening on the corresp. sctp socket
251
+   return 0 on success, -1 on error */
252
+int sctp_init_sock(struct socket_info* sock_info)
253
+{
254
+	union sockaddr_union* addr;
255
+	
256
+	sock_info->proto=PROTO_SCTP;
257
+	addr=&sock_info->su;
258
+	if (sctp_init_su(sock_info)!=0)
259
+		goto error;
260
+	sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_SEQPACKET, 
261
+								IPPROTO_SCTP);
262
+	if (sock_info->socket==-1){
263
+		LOG(L_ERR, "ERROR: sctp_init_sock: socket: %s\n", strerror(errno));
264
+		goto error;
265
+	}
266
+	INFO("sctp: socket %d initialized (%p)\n", sock_info->socket, sock_info);
267
+	/* make socket non-blocking */
268
+#if 0
269
+	/* recvmsg must block so use blocking sockets
270
+	 * and send with MSG_DONTWAIT */
271
+	optval=fcntl(sock_info->socket, F_GETFL);
272
+	if (optval==-1){
273
+		LOG(L_ERR, "ERROR: init_sctp: fnctl failed: (%d) %s\n",
274
+				errno, strerror(errno));
275
+		goto error;
276
+	}
277
+	if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
278
+		LOG(L_ERR, "ERROR: init_sctp: fcntl: set non-blocking failed:"
279
+				" (%d) %s\n", errno, strerror(errno));
280
+		goto error;
281
+	}
282
+#endif
283
+
284
+	/* set sock opts */
285
+	if (sctp_init_sock_opt_common(sock_info->socket)!=0)
286
+		goto error;
287
+	/* SCTP_EVENTS for send dried out -> present in the draft not yet
288
+	 * present in linux (might help to detect when we could send again to
289
+	 * some peer, kind of poor's man poll on write, based on received
290
+	 * SCTP_SENDER_DRY_EVENTs */
291
+	
292
+	if (sctp_bind_sock(sock_info)<0)
293
+		goto error;
243 294
 	if (listen(sock_info->socket, 1)<0){
244 295
 		LOG(L_ERR, "ERROR: sctp_init_sock: listen(%x, 1) on %s: %s\n",
245 296
 					sock_info->socket, sock_info->address_str.s,