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