Commit | Line | Data |
---|---|---|
127f7d76 | 1 | /* uipc_syscalls.c 4.39 82/12/28 */ |
c8c7dd0e BJ |
2 | |
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
7 | #include "../h/proc.h" | |
8 | #include "../h/file.h" | |
9 | #include "../h/inode.h" | |
10 | #include "../h/buf.h" | |
11 | #include "../h/mbuf.h" | |
c8c7dd0e BJ |
12 | #include "../h/protosw.h" |
13 | #include "../h/socket.h" | |
14 | #include "../h/socketvar.h" | |
4147b3f6 | 15 | #include "../h/descrip.h" |
a6b6f679 | 16 | #include "../h/uio.h" |
4147b3f6 | 17 | |
c8c7dd0e | 18 | /* |
cf012934 | 19 | * System call interface to the socket abstraction. |
c8c7dd0e BJ |
20 | */ |
21 | ||
cf012934 | 22 | socket() |
c8c7dd0e | 23 | { |
cc15ab5d | 24 | register struct a { |
cf012934 | 25 | int domain; |
cc15ab5d | 26 | int type; |
cf012934 BJ |
27 | int protocol; |
28 | struct socketopt *opt; | |
cc15ab5d | 29 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 30 | struct socket *so; |
cc15ab5d | 31 | register struct file *fp; |
cf012934 | 32 | struct socketopt aopt; |
c8c7dd0e | 33 | |
b32450f4 | 34 | u.u_error = sockopt(&aopt, (caddr_t)uap->opt); |
dfb67abe | 35 | if (u.u_error) |
cc15ab5d | 36 | return; |
dfb67abe BJ |
37 | if ((fp = falloc()) == NULL) |
38 | goto freeopt; | |
4147b3f6 BJ |
39 | fp->f_flag = FREAD|FWRITE; |
40 | fp->f_type = DTYPE_SOCKET; | |
76d78581 | 41 | u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol, &aopt); |
cc15ab5d BJ |
42 | if (u.u_error) |
43 | goto bad; | |
2b4b57cd | 44 | fp->f_socket = so; |
cf012934 BJ |
45 | freeopt: |
46 | if (uap->opt) | |
39d536e6 | 47 | (void) m_free(dtom(aopt.so_optdata)); |
cc15ab5d BJ |
48 | return; |
49 | bad: | |
50 | u.u_ofile[u.u_r.r_val1] = 0; | |
51 | fp->f_count = 0; | |
cf012934 | 52 | goto freeopt; |
c8c7dd0e | 53 | } |
ae921915 | 54 | |
cf012934 | 55 | bind() |
ae921915 | 56 | { |
2b4b57cd | 57 | register struct a { |
cf012934 BJ |
58 | int s; |
59 | caddr_t name; | |
60 | int namelen; | |
61 | struct socketopt *opt; | |
2b4b57cd | 62 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 63 | register struct file *fp; |
cf012934 BJ |
64 | struct mbuf *nam; |
65 | struct socketopt aopt; | |
ae921915 | 66 | |
cf012934 BJ |
67 | fp = getf(uap->s); |
68 | if (fp == 0) | |
69 | return; | |
70 | if (fp->f_type != DTYPE_SOCKET) { | |
71 | u.u_error = ENOTSOCK; | |
2b4b57cd BJ |
72 | return; |
73 | } | |
cf012934 BJ |
74 | u.u_error = sockname(&nam, uap->name, uap->namelen); |
75 | if (u.u_error) | |
76 | return; | |
b32450f4 | 77 | u.u_error = sockopt(&aopt, (caddr_t)uap->opt); |
cf012934 BJ |
78 | if (u.u_error) { |
79 | m_freem(nam); | |
970108c7 | 80 | goto freeopt; |
cf012934 BJ |
81 | } |
82 | u.u_error = sobind(fp->f_socket, nam, &aopt); | |
83 | m_freem(nam); | |
970108c7 | 84 | freeopt: |
cf012934 | 85 | if (uap->opt) |
39d536e6 | 86 | (void) m_free(dtom(aopt.so_optdata)); |
cf012934 BJ |
87 | } |
88 | ||
89 | listen() | |
90 | { | |
91 | register struct a { | |
92 | int s; | |
93 | int backlog; | |
94 | } *uap = (struct a *)u.u_ap; | |
95 | register struct file *fp; | |
96 | ||
97 | fp = getf(uap->s); | |
2b4b57cd BJ |
98 | if (fp == 0) |
99 | return; | |
4147b3f6 | 100 | if (fp->f_type != DTYPE_SOCKET) { |
2b4b57cd BJ |
101 | u.u_error = ENOTSOCK; |
102 | return; | |
103 | } | |
cf012934 BJ |
104 | u.u_error = solisten(fp->f_socket, uap->backlog); |
105 | } | |
106 | ||
107 | accept() | |
108 | { | |
109 | register struct a { | |
110 | int s; | |
111 | caddr_t name; | |
112 | int *anamelen; | |
113 | struct socketopt *opt; | |
114 | } *uap = (struct a *)u.u_ap; | |
115 | register struct file *fp; | |
116 | struct mbuf *nam; | |
117 | struct socketopt aopt; | |
118 | int namelen; | |
119 | int s; | |
120 | register struct socket *so; | |
121 | ||
122 | if (uap->name == 0) | |
123 | goto noname; | |
127f7d76 SL |
124 | u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, |
125 | sizeof (namelen)); | |
126 | if (u.u_error) | |
cf012934 | 127 | return; |
b32450f4 | 128 | if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { |
cf012934 BJ |
129 | u.u_error = EFAULT; |
130 | return; | |
131 | } | |
132 | noname: | |
b32450f4 | 133 | u.u_error = sockopt(&aopt, (caddr_t)uap->opt); |
cf012934 BJ |
134 | if (u.u_error) |
135 | return; | |
136 | fp = getf(uap->s); | |
137 | if (fp == 0) | |
138 | goto bad; | |
139 | if (fp->f_type != DTYPE_SOCKET) { | |
140 | u.u_error = ENOTSOCK; | |
141 | goto bad; | |
142 | } | |
2b4b57cd BJ |
143 | s = splnet(); |
144 | so = fp->f_socket; | |
4147b3f6 BJ |
145 | if ((so->so_options & SO_ACCEPTCONN) == 0) { |
146 | u.u_error = EINVAL; | |
147 | splx(s); | |
cf012934 | 148 | goto bad; |
4147b3f6 BJ |
149 | } |
150 | if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { | |
2b4b57cd BJ |
151 | u.u_error = EWOULDBLOCK; |
152 | splx(s); | |
cf012934 | 153 | goto bad; |
2b4b57cd | 154 | } |
4147b3f6 | 155 | while (so->so_qlen == 0 && so->so_error == 0) { |
62229532 BJ |
156 | if (so->so_state & SS_CANTRCVMORE) { |
157 | so->so_error = ECONNABORTED; | |
158 | break; | |
159 | } | |
d08c5322 | 160 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
62229532 | 161 | } |
f269ef23 BJ |
162 | if (so->so_error) { |
163 | u.u_error = so->so_error; | |
164 | splx(s); | |
cf012934 | 165 | goto bad; |
f269ef23 | 166 | } |
4147b3f6 BJ |
167 | if ((so->so_options & SO_NEWFDONCONN) == 0) { |
168 | struct socket *nso = so->so_q; | |
169 | (void) soqremque(nso, 1); | |
6e7edb25 | 170 | u.u_error = soclose(so, 1); |
4147b3f6 BJ |
171 | fp->f_socket = nso; |
172 | nso->so_q = 0; | |
173 | so = nso; | |
174 | goto ret; | |
175 | } | |
176 | if (ufalloc() < 0) { | |
177 | splx(s); | |
cf012934 | 178 | goto bad; |
4147b3f6 BJ |
179 | } |
180 | fp = falloc(); | |
181 | if (fp == 0) { | |
182 | u.u_ofile[u.u_r.r_val1] = 0; | |
2b4b57cd | 183 | splx(s); |
cf012934 BJ |
184 | goto bad; |
185 | } | |
186 | { struct socket *aso = so->so_q; | |
187 | if (soqremque(aso, 1) == 0) | |
188 | panic("accept"); | |
189 | so = aso; | |
2b4b57cd | 190 | } |
4147b3f6 BJ |
191 | fp->f_type = DTYPE_SOCKET; |
192 | fp->f_flag = FREAD|FWRITE; | |
cf012934 | 193 | fp->f_socket = so; |
4147b3f6 | 194 | ret: |
cce93e4b | 195 | nam = m_get(M_WAIT, MT_SONAME); |
5a1f132a | 196 | (void) soaccept(so, nam, &aopt); |
cf012934 BJ |
197 | if (uap->name) { |
198 | if (namelen > nam->m_len) | |
199 | namelen = nam->m_len; | |
200 | /* SHOULD COPY OUT A CHAIN HERE */ | |
b32450f4 BJ |
201 | (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, |
202 | (u_int)namelen); | |
203 | (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, | |
cf012934 BJ |
204 | sizeof (*uap->anamelen)); |
205 | } | |
206 | m_freem(nam); | |
2b4b57cd | 207 | splx(s); |
cf012934 BJ |
208 | bad: |
209 | if (uap->opt) | |
39d536e6 | 210 | (void) m_free(dtom(aopt.so_optdata)); |
ae921915 BJ |
211 | } |
212 | ||
cf012934 | 213 | connect() |
c8c7dd0e BJ |
214 | { |
215 | register struct a { | |
cf012934 BJ |
216 | int s; |
217 | caddr_t name; | |
218 | int namelen; | |
219 | struct socketopt *opt; | |
c8c7dd0e | 220 | } *uap = (struct a *)u.u_ap; |
c8c7dd0e BJ |
221 | register struct file *fp; |
222 | register struct socket *so; | |
cf012934 BJ |
223 | struct mbuf *nam; |
224 | struct socketopt aopt; | |
c8c7dd0e BJ |
225 | int s; |
226 | ||
cf012934 | 227 | fp = getf(uap->s); |
c8c7dd0e BJ |
228 | if (fp == 0) |
229 | return; | |
4147b3f6 | 230 | if (fp->f_type != DTYPE_SOCKET) { |
c8c7dd0e BJ |
231 | u.u_error = ENOTSOCK; |
232 | return; | |
233 | } | |
234 | so = fp->f_socket; | |
cf012934 | 235 | u.u_error = sockname(&nam, uap->name, uap->namelen); |
c8c7dd0e BJ |
236 | if (u.u_error) |
237 | return; | |
b32450f4 | 238 | u.u_error = sockopt(&aopt, (caddr_t)uap->opt); |
cf012934 BJ |
239 | if (u.u_error) { |
240 | m_freem(nam); | |
241 | return; | |
242 | } | |
243 | u.u_error = soconnect(so, nam, &aopt); | |
244 | if (u.u_error) | |
245 | goto bad; | |
c8c7dd0e | 246 | s = splnet(); |
62364f0e | 247 | if ((so->so_state & SS_NBIO) && |
cc15ab5d | 248 | (so->so_state & SS_ISCONNECTING)) { |
c8c7dd0e | 249 | u.u_error = EINPROGRESS; |
cc15ab5d | 250 | splx(s); |
cf012934 | 251 | goto bad; |
c8c7dd0e | 252 | } |
cc15ab5d | 253 | while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) |
c8c7dd0e BJ |
254 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
255 | u.u_error = so->so_error; | |
cc15ab5d BJ |
256 | so->so_error = 0; |
257 | splx(s); | |
cf012934 BJ |
258 | bad: |
259 | m_freem(nam); | |
260 | if (uap->opt) | |
39d536e6 | 261 | (void) m_free(dtom(aopt.so_optdata)); |
cf012934 | 262 | return; |
c8c7dd0e BJ |
263 | } |
264 | ||
cf012934 BJ |
265 | socketpair() |
266 | { | |
267 | ||
268 | u.u_error = ENOENT; | |
269 | } | |
270 | ||
271 | sendto() | |
c8c7dd0e BJ |
272 | { |
273 | register struct a { | |
cf012934 BJ |
274 | int s; |
275 | caddr_t buf; | |
276 | int len; | |
277 | int flags; | |
278 | caddr_t to; | |
279 | int tolen; | |
c8c7dd0e BJ |
280 | } *uap = (struct a *)u.u_ap; |
281 | register struct file *fp; | |
d3d550b5 BJ |
282 | struct uio auio; |
283 | struct iovec aiov; | |
cf012934 | 284 | struct mbuf *to; |
c8c7dd0e | 285 | |
cf012934 | 286 | fp = getf(uap->s); |
c8c7dd0e BJ |
287 | if (fp == 0) |
288 | return; | |
4147b3f6 | 289 | if (fp->f_type != DTYPE_SOCKET) { |
c8c7dd0e BJ |
290 | u.u_error = ENOTSOCK; |
291 | return; | |
292 | } | |
d3d550b5 BJ |
293 | auio.uio_iov = &aiov; |
294 | auio.uio_iovcnt = 1; | |
cf012934 BJ |
295 | aiov.iov_base = uap->buf; |
296 | aiov.iov_len = uap->len; | |
297 | auio.uio_resid = uap->len; | |
d3d550b5 BJ |
298 | auio.uio_segflg = 0; |
299 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 300 | if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { |
c8c7dd0e BJ |
301 | u.u_error = EFAULT; |
302 | return; | |
303 | } | |
cf012934 BJ |
304 | u.u_error = sockname(&to, uap->to, uap->tolen); |
305 | if (u.u_error) | |
306 | goto bad; | |
970108c7 | 307 | u.u_error = sosend(fp->f_socket, to, &auio, uap->flags); |
76d78581 | 308 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
cf012934 BJ |
309 | bad: |
310 | m_freem(to); | |
c8c7dd0e BJ |
311 | } |
312 | ||
cf012934 | 313 | send() |
cc15ab5d BJ |
314 | { |
315 | register struct a { | |
cf012934 BJ |
316 | int s; |
317 | caddr_t buf; | |
318 | int len; | |
319 | int flags; | |
cc15ab5d BJ |
320 | } *uap = (struct a *)u.u_ap; |
321 | register struct file *fp; | |
a6b6f679 BJ |
322 | struct uio auio; |
323 | struct iovec aiov; | |
cc15ab5d | 324 | |
cf012934 BJ |
325 | fp = getf(uap->s); |
326 | if (fp == 0) | |
327 | return; | |
328 | if (fp->f_type != DTYPE_SOCKET) { | |
329 | u.u_error = ENOTSOCK; | |
330 | return; | |
331 | } | |
332 | auio.uio_iov = &aiov; | |
333 | auio.uio_iovcnt = 1; | |
334 | aiov.iov_base = uap->buf; | |
335 | aiov.iov_len = uap->len; | |
336 | auio.uio_resid = uap->len; | |
337 | auio.uio_segflg = 0; | |
338 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 339 | if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { |
cf012934 BJ |
340 | u.u_error = EFAULT; |
341 | return; | |
342 | } | |
343 | if (u.u_error) | |
344 | return; | |
970108c7 | 345 | u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags); |
76d78581 | 346 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
cf012934 BJ |
347 | } |
348 | ||
349 | recvfrom() | |
350 | { | |
351 | register struct a { | |
352 | int s; | |
353 | caddr_t buf; | |
354 | int len; | |
355 | int flags; | |
356 | caddr_t from; | |
357 | int *fromlenaddr; | |
358 | } *uap = (struct a *)u.u_ap; | |
359 | register struct file *fp; | |
360 | struct uio auio; | |
361 | struct iovec aiov; | |
362 | struct mbuf *from; | |
363 | int fromlen; | |
364 | ||
127f7d76 SL |
365 | u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, |
366 | sizeof (fromlen)); | |
367 | if (u.u_error) | |
cf012934 | 368 | return; |
cf012934 BJ |
369 | fp = getf(uap->s); |
370 | if (fp == 0) | |
371 | return; | |
372 | if (fp->f_type != DTYPE_SOCKET) { | |
373 | u.u_error = ENOTSOCK; | |
374 | return; | |
375 | } | |
376 | auio.uio_iov = &aiov; | |
377 | auio.uio_iovcnt = 1; | |
378 | aiov.iov_base = uap->buf; | |
379 | aiov.iov_len = uap->len; | |
380 | auio.uio_resid = uap->len; | |
381 | auio.uio_segflg = 0; | |
382 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 383 | if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { |
cf012934 BJ |
384 | u.u_error = EFAULT; |
385 | return; | |
386 | } | |
387 | from = 0; | |
970108c7 | 388 | u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags); |
cf012934 BJ |
389 | if (u.u_error) |
390 | goto bad; | |
391 | if (from == 0) | |
392 | fromlen = 0; | |
393 | else { | |
394 | if (fromlen > from->m_len) | |
395 | fromlen = from->m_len; | |
127f7d76 SL |
396 | u.u_error = copyout(mtod(from, caddr_t), uap->from, |
397 | (u_int)fromlen); | |
398 | if (u.u_error) | |
cf012934 | 399 | goto bad; |
cf012934 | 400 | } |
127f7d76 SL |
401 | u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, |
402 | sizeof (fromlen)); | |
403 | if (u.u_error) | |
cf012934 | 404 | goto bad; |
cf012934 BJ |
405 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
406 | bad: | |
407 | if (from) | |
408 | m_freem(from); | |
409 | return; | |
410 | } | |
411 | ||
412 | recv() | |
413 | { | |
414 | register struct a { | |
415 | int s; | |
416 | caddr_t buf; | |
417 | int len; | |
418 | int flags; | |
419 | } *uap = (struct a *)u.u_ap; | |
420 | register struct file *fp; | |
421 | struct uio auio; | |
422 | struct iovec aiov; | |
423 | ||
424 | fp = getf(uap->s); | |
cc15ab5d BJ |
425 | if (fp == 0) |
426 | return; | |
4147b3f6 | 427 | if (fp->f_type != DTYPE_SOCKET) { |
cc15ab5d BJ |
428 | u.u_error = ENOTSOCK; |
429 | return; | |
430 | } | |
a6b6f679 BJ |
431 | auio.uio_iov = &aiov; |
432 | auio.uio_iovcnt = 1; | |
cf012934 BJ |
433 | aiov.iov_base = uap->buf; |
434 | aiov.iov_len = uap->len; | |
435 | auio.uio_resid = uap->len; | |
a6b6f679 BJ |
436 | auio.uio_segflg = 0; |
437 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 438 | if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { |
cc15ab5d BJ |
439 | u.u_error = EFAULT; |
440 | return; | |
441 | } | |
b32450f4 BJ |
442 | u.u_error = |
443 | soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); | |
cf012934 BJ |
444 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
445 | } | |
446 | ||
447 | sendmsg() | |
448 | { | |
449 | ||
450 | u.u_error = EINVAL; | |
451 | } | |
452 | ||
453 | recvmsg() | |
454 | { | |
455 | ||
456 | u.u_error = EINVAL; | |
457 | } | |
458 | ||
459 | shutdown() | |
460 | { | |
461 | ||
462 | u.u_error = EINVAL; | |
463 | } | |
464 | ||
465 | pipe() | |
466 | { | |
467 | register struct file *rf, *wf; | |
468 | struct socket *rso, *wso; | |
469 | int r; | |
470 | ||
4f083fd7 SL |
471 | u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, |
472 | (struct socketopt *)0); | |
2b4b57cd BJ |
473 | if (u.u_error) |
474 | return; | |
4f083fd7 SL |
475 | u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, |
476 | (struct socketopt *)0); | |
cf012934 BJ |
477 | if (u.u_error) |
478 | goto free; | |
479 | rf = falloc(); | |
480 | if (rf == NULL) | |
481 | goto free2; | |
482 | r = u.u_r.r_val1; | |
483 | rf->f_flag = FREAD; | |
484 | rf->f_type = DTYPE_SOCKET; | |
485 | rf->f_socket = rso; | |
486 | wf = falloc(); | |
487 | if (wf == NULL) | |
488 | goto free3; | |
489 | wf->f_flag = FWRITE; | |
490 | wf->f_type = DTYPE_SOCKET; | |
491 | wf->f_socket = wso; | |
492 | u.u_r.r_val2 = u.u_r.r_val1; | |
493 | u.u_r.r_val1 = r; | |
494 | if (piconnect(wso, rso) == 0) | |
495 | goto free4; | |
496 | return; | |
497 | free4: | |
498 | wf->f_count = 0; | |
499 | u.u_ofile[u.u_r.r_val2] = 0; | |
500 | free3: | |
501 | rf->f_count = 0; | |
502 | u.u_ofile[r] = 0; | |
503 | free2: | |
504 | wso->so_state |= SS_NOFDREF; | |
505 | sofree(wso); | |
506 | free: | |
507 | rso->so_state |= SS_NOFDREF; | |
508 | sofree(rso); | |
cc15ab5d | 509 | } |
a3076b07 BJ |
510 | |
511 | /* | |
512 | * Get socket address. | |
513 | */ | |
514 | ssocketaddr() | |
515 | { | |
516 | register struct a { | |
517 | int fdes; | |
518 | struct sockaddr *asa; | |
519 | } *uap = (struct a *)u.u_ap; | |
520 | register struct file *fp; | |
05d69517 | 521 | register struct socket *so; |
cf012934 | 522 | struct mbuf *m; |
a3076b07 BJ |
523 | |
524 | fp = getf(uap->fdes); | |
525 | if (fp == 0) | |
526 | return; | |
4147b3f6 | 527 | if (fp->f_type != DTYPE_SOCKET) { |
a3076b07 BJ |
528 | u.u_error = ENOTSOCK; |
529 | return; | |
530 | } | |
05d69517 | 531 | so = fp->f_socket; |
cce93e4b | 532 | m = m_getclr(M_WAIT, MT_SONAME); |
05d69517 | 533 | u.u_error = |
cf012934 | 534 | (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); |
05d69517 | 535 | if (u.u_error) |
cf012934 | 536 | goto bad; |
127f7d76 SL |
537 | u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, |
538 | sizeof (struct sockaddr)); | |
cf012934 BJ |
539 | bad: |
540 | m_freem(m); | |
541 | } | |
542 | ||
543 | sockname(aname, name, namelen) | |
544 | struct mbuf **aname; | |
545 | caddr_t name; | |
546 | int namelen; | |
547 | { | |
548 | register struct mbuf *m; | |
127f7d76 | 549 | int error; |
cf012934 BJ |
550 | |
551 | if (namelen > MLEN) | |
552 | return (EINVAL); | |
cce93e4b | 553 | m = m_get(M_WAIT, MT_SONAME); |
cf012934 | 554 | m->m_len = namelen; |
127f7d76 SL |
555 | error = copyin(name, mtod(m, caddr_t), (u_int)namelen); |
556 | if (error) | |
cf012934 | 557 | (void) m_free(m); |
127f7d76 SL |
558 | else |
559 | *aname = m; | |
560 | return (error); | |
cf012934 BJ |
561 | } |
562 | ||
563 | sockopt(so, opt) | |
564 | register struct socketopt *so; | |
565 | caddr_t opt; | |
566 | { | |
567 | register struct mbuf *m; | |
127f7d76 | 568 | int error; |
cf012934 BJ |
569 | |
570 | if (opt == 0) { | |
571 | so->so_optlen = 0; | |
572 | so->so_optdata = 0; | |
573 | return (0); | |
574 | } | |
127f7d76 SL |
575 | error = copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt)); |
576 | if (error) | |
577 | return (error); | |
cf012934 BJ |
578 | if (so->so_optlen < 0 || so->so_optlen > MLEN) |
579 | return (EINVAL); | |
cce93e4b | 580 | m = m_get(M_WAIT, MT_SOOPTS); |
cf012934 | 581 | m->m_len = so->so_optlen; |
127f7d76 SL |
582 | error = copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len); |
583 | if (error) { | |
cf012934 | 584 | (void) m_free(m); |
127f7d76 | 585 | return (error); |
cf012934 BJ |
586 | } |
587 | so->so_optdata = mtod(m, caddr_t); | |
588 | return (0); | |
2752c877 | 589 | } |