xref: /csrg-svn/sys/kern/uipc_socket.c (revision 23233)
1 /*	uipc_socket.c	6.14	85/06/08	*/
2 
3 #include "param.h"
4 #include "systm.h"
5 #include "dir.h"
6 #include "user.h"
7 #include "proc.h"
8 #include "file.h"
9 #include "inode.h"
10 #include "buf.h"
11 #include "mbuf.h"
12 #include "un.h"
13 #include "domain.h"
14 #include "protosw.h"
15 #include "socket.h"
16 #include "socketvar.h"
17 #include "stat.h"
18 #include "ioctl.h"
19 #include "uio.h"
20 #include "../net/route.h"
21 #include "../netinet/in.h"
22 #include "../net/if.h"
23 
24 /*
25  * Socket operation routines.
26  * These routines are called by the routines in
27  * sys_socket.c or from a system process, and
28  * implement the semantics of socket operations by
29  * switching out to the protocol specific routines.
30  *
31  * TODO:
32  *	test socketpair
33  *	clean up async
34  *	out-of-band is a kludge
35  */
36 /*ARGSUSED*/
37 socreate(dom, aso, type, proto)
38 	struct socket **aso;
39 	register int type;
40 	int proto;
41 {
42 	register struct protosw *prp;
43 	register struct socket *so;
44 	register struct mbuf *m;
45 	register int error;
46 
47 	if (proto)
48 		prp = pffindproto(dom, proto, type);
49 	else
50 		prp = pffindtype(dom, type);
51 	if (prp == 0)
52 		return (EPROTONOSUPPORT);
53 	if (prp->pr_type != type)
54 		return (EPROTOTYPE);
55 	m = m_getclr(M_WAIT, MT_SOCKET);
56 	so = mtod(m, struct socket *);
57 	so->so_options = 0;
58 	so->so_state = 0;
59 	so->so_type = type;
60 	if (u.u_uid == 0)
61 		so->so_state = SS_PRIV;
62 	so->so_proto = prp;
63 	error =
64 	    (*prp->pr_usrreq)(so, PRU_ATTACH,
65 		(struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
66 	if (error) {
67 		so->so_state |= SS_NOFDREF;
68 		sofree(so);
69 		return (error);
70 	}
71 	*aso = so;
72 	return (0);
73 }
74 
75 sobind(so, nam)
76 	struct socket *so;
77 	struct mbuf *nam;
78 {
79 	int s = splnet();
80 	int error;
81 
82 	error =
83 	    (*so->so_proto->pr_usrreq)(so, PRU_BIND,
84 		(struct mbuf *)0, nam, (struct mbuf *)0);
85 	splx(s);
86 	return (error);
87 }
88 
89 solisten(so, backlog)
90 	register struct socket *so;
91 	int backlog;
92 {
93 	int s = splnet(), error;
94 
95 	error =
96 	    (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
97 		(struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
98 	if (error) {
99 		splx(s);
100 		return (error);
101 	}
102 	if (so->so_q == 0) {
103 		so->so_q = so;
104 		so->so_q0 = so;
105 		so->so_options |= SO_ACCEPTCONN;
106 	}
107 	if (backlog < 0)
108 		backlog = 0;
109 	so->so_qlimit = MIN(backlog, SOMAXCONN);
110 	splx(s);
111 	return (0);
112 }
113 
114 sofree(so)
115 	register struct socket *so;
116 {
117 
118 	if (so->so_head) {
119 		if (!soqremque(so, 0) && !soqremque(so, 1))
120 			panic("sofree dq");
121 		so->so_head = 0;
122 	}
123 	if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
124 		return;
125 	sbrelease(&so->so_snd);
126 	sorflush(so);
127 	(void) m_free(dtom(so));
128 }
129 
130 /*
131  * Close a socket on last file table reference removal.
132  * Initiate disconnect if connected.
133  * Free socket when disconnect complete.
134  */
135 soclose(so)
136 	register struct socket *so;
137 {
138 	int s = splnet();		/* conservative */
139 	int error;
140 
141 	if (so->so_options & SO_ACCEPTCONN) {
142 		while (so->so_q0 != so)
143 			(void) soabort(so->so_q0);
144 		while (so->so_q != so)
145 			(void) soabort(so->so_q);
146 	}
147 	if (so->so_pcb == 0)
148 		goto discard;
149 	if (so->so_state & SS_ISCONNECTED) {
150 		if ((so->so_state & SS_ISDISCONNECTING) == 0) {
151 			error = sodisconnect(so, (struct mbuf *)0);
152 			if (error)
153 				goto drop;
154 		}
155 		if (so->so_options & SO_LINGER) {
156 			if ((so->so_state & SS_ISDISCONNECTING) &&
157 			    (so->so_state & SS_NBIO))
158 				goto drop;
159 			while (so->so_state & SS_ISCONNECTED)
160 				sleep((caddr_t)&so->so_timeo, PZERO+1);
161 		}
162 	}
163 drop:
164 	if (so->so_pcb) {
165 		int error2 =
166 		    (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
167 			(struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
168 		if (error == 0)
169 			error = error2;
170 	}
171 discard:
172 	if (so->so_state & SS_NOFDREF)
173 		panic("soclose: NOFDREF");
174 	so->so_state |= SS_NOFDREF;
175 	sofree(so);
176 	splx(s);
177 	return (error);
178 }
179 
180 /*
181  * Must be called at splnet...
182  */
183 soabort(so)
184 	struct socket *so;
185 {
186 
187 	return (
188 	    (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
189 		(struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
190 }
191 
192 soaccept(so, nam)
193 	register struct socket *so;
194 	struct mbuf *nam;
195 {
196 	int s = splnet();
197 	int error;
198 
199 	if ((so->so_state & SS_NOFDREF) == 0)
200 		panic("soaccept: !NOFDREF");
201 	so->so_state &= ~SS_NOFDREF;
202 	error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
203 	    (struct mbuf *)0, nam, (struct mbuf *)0);
204 	splx(s);
205 	return (error);
206 }
207 
208 soconnect(so, nam)
209 	register struct socket *so;
210 	struct mbuf *nam;
211 {
212 	int s = splnet();
213 	int error;
214 
215 	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
216 		error = EISCONN;
217 		goto bad;
218 	}
219 	error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
220 	    (struct mbuf *)0, nam, (struct mbuf *)0);
221 bad:
222 	splx(s);
223 	return (error);
224 }
225 
226 soconnect2(so1, so2)
227 	register struct socket *so1;
228 	struct socket *so2;
229 {
230 	int s = splnet();
231 	int error;
232 
233 	error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
234 	    (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
235 	splx(s);
236 	return (error);
237 }
238 
239 sodisconnect(so, nam)
240 	register struct socket *so;
241 	struct mbuf *nam;
242 {
243 	int s = splnet();
244 	int error;
245 
246 	if ((so->so_state & SS_ISCONNECTED) == 0) {
247 		error = ENOTCONN;
248 		goto bad;
249 	}
250 	if (so->so_state & SS_ISDISCONNECTING) {
251 		error = EALREADY;
252 		goto bad;
253 	}
254 	error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
255 	    (struct mbuf *)0, nam, (struct mbuf *)0);
256 bad:
257 	splx(s);
258 	return (error);
259 }
260 
261 /*
262  * Send on a socket.
263  * If send must go all at once and message is larger than
264  * send buffering, then hard error.
265  * Lock against other senders.
266  * If must go all at once and not enough room now, then
267  * inform user that this would block and do nothing.
268  * Otherwise, if nonblocking, send as much as possible.
269  */
270 sosend(so, nam, uio, flags, rights)
271 	register struct socket *so;
272 	struct mbuf *nam;
273 	register struct uio *uio;
274 	int flags;
275 	struct mbuf *rights;
276 {
277 	struct mbuf *top = 0;
278 	register struct mbuf *m, **mp;
279 	register int space;
280 	int len, error = 0, s, dontroute, first = 1;
281 
282 	if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
283 		return (EMSGSIZE);
284 	dontroute =
285 	    (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
286 	    (so->so_proto->pr_flags & PR_ATOMIC);
287 	u.u_ru.ru_msgsnd++;
288 #define	snderr(errno)	{ error = errno; splx(s); goto release; }
289 
290 restart:
291 	sblock(&so->so_snd);
292 	do {
293 		s = splnet();
294 		if (so->so_state & SS_CANTSENDMORE)
295 			snderr(EPIPE);
296 		if (so->so_error) {
297 			error = so->so_error;
298 			so->so_error = 0;			/* ??? */
299 			splx(s);
300 			goto release;
301 		}
302 		if ((so->so_state & SS_ISCONNECTED) == 0) {
303 			if (so->so_proto->pr_flags & PR_CONNREQUIRED)
304 				snderr(ENOTCONN);
305 			if (nam == 0)
306 				snderr(EDESTADDRREQ);
307 		}
308 		if (flags & MSG_OOB)
309 			space = 1024;
310 		else {
311 			space = sbspace(&so->so_snd);
312 			if (space <= 0 ||
313 			   (sosendallatonce(so) && space < uio->uio_resid) ||
314 			   (uio->uio_resid >= CLBYTES && space < CLBYTES &&
315 			   so->so_snd.sb_cc >= CLBYTES &&
316 			   (so->so_state & SS_NBIO) == 0)) {
317 				if (so->so_state & SS_NBIO) {
318 					if (first)
319 						error = EWOULDBLOCK;
320 					splx(s);
321 					goto release;
322 				}
323 				sbunlock(&so->so_snd);
324 				sbwait(&so->so_snd);
325 				splx(s);
326 				goto restart;
327 			}
328 		}
329 		splx(s);
330 		mp = &top;
331 		while (space > 0) {
332 			register struct iovec *iov = uio->uio_iov;
333 
334 			MGET(m, M_WAIT, MT_DATA);
335 			if (iov->iov_len >= NBPG && space >= CLBYTES) {
336 				register struct mbuf *p;
337 				MCLGET(p, 1);
338 				if (p == 0)
339 					goto nopages;
340 				m->m_off = (int)p - (int)m;
341 				len = min(CLBYTES, iov->iov_len);
342 				space -= CLBYTES;
343 			} else {
344 nopages:
345 				len = MIN(MLEN, iov->iov_len);
346 				space -= len;
347 			}
348 			error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
349 			m->m_len = len;
350 			*mp = m;
351 			if (error)
352 				goto release;
353 			mp = &m->m_next;
354 			if (uio->uio_resid <= 0)
355 				break;
356 			while (uio->uio_iov->iov_len == 0) {
357 				uio->uio_iov++;
358 				uio->uio_iovcnt--;
359 				if (uio->uio_iovcnt <= 0)
360 					panic("sosend");
361 			}
362 		}
363 		if (dontroute)
364 			so->so_options |= SO_DONTROUTE;
365 		s = splnet();					/* XXX */
366 		error = (*so->so_proto->pr_usrreq)(so,
367 		    (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
368 		    top, (caddr_t)nam, rights);
369 		splx(s);
370 		if (dontroute)
371 			so->so_options &= ~SO_DONTROUTE;
372 		rights = 0;
373 		top = 0;
374 		first = 0;
375 		if (error)
376 			break;
377 	} while (uio->uio_resid);
378 
379 release:
380 	sbunlock(&so->so_snd);
381 	if (top)
382 		m_freem(top);
383 	if (error == EPIPE)
384 		psignal(u.u_procp, SIGPIPE);
385 	return (error);
386 }
387 
388 soreceive(so, aname, uio, flags, rightsp)
389 	register struct socket *so;
390 	struct mbuf **aname;
391 	register struct uio *uio;
392 	int flags;
393 	struct mbuf **rightsp;
394 {
395 	register struct mbuf *m, *n;
396 	register int len, error = 0, s, tomark;
397 	struct protosw *pr = so->so_proto;
398 	struct mbuf *nextrecord;
399 	int moff;
400 
401 	if (rightsp)
402 		*rightsp = 0;
403 	if (aname)
404 		*aname = 0;
405 	if (flags & MSG_OOB) {
406 		m = m_get(M_WAIT, MT_DATA);
407 		error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
408 		    m, (struct mbuf *)0, (struct mbuf *)0);
409 		if (error)
410 			goto bad;
411 		do {
412 			len = uio->uio_resid;
413 			if (len > m->m_len)
414 				len = m->m_len;
415 			error =
416 			    uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
417 			m = m_free(m);
418 		} while (uio->uio_resid && error == 0 && m);
419 bad:
420 		if (m)
421 			m_freem(m);
422 		return (error);
423 	}
424 
425 restart:
426 	sblock(&so->so_rcv);
427 	s = splnet();
428 
429 #define	rcverr(errno)	{ error = errno; splx(s); goto release; }
430 	if (so->so_rcv.sb_cc == 0) {
431 		if (so->so_error) {
432 			error = so->so_error;
433 			so->so_error = 0;
434 			splx(s);
435 			goto release;
436 		}
437 		if (so->so_state & SS_CANTRCVMORE) {
438 			splx(s);
439 			goto release;
440 		}
441 		if ((so->so_state & SS_ISCONNECTED) == 0 &&
442 		    (so->so_proto->pr_flags & PR_CONNREQUIRED))
443 			rcverr(ENOTCONN);
444 		if (so->so_state & SS_NBIO)
445 			rcverr(EWOULDBLOCK);
446 		sbunlock(&so->so_rcv);
447 		sbwait(&so->so_rcv);
448 		splx(s);
449 		goto restart;
450 	}
451 	u.u_ru.ru_msgrcv++;
452 	m = so->so_rcv.sb_mb;
453 	if (pr->pr_flags & PR_ADDR) {
454 		if (m == 0 || m->m_type != MT_SONAME)
455 			panic("receive 1a");
456 		if (flags & MSG_PEEK) {
457 			if (aname)
458 				*aname = m_copy(m, 0, m->m_len);
459 			else
460 				m = m->m_act;
461 		} else {
462 			if (aname) {
463 				*aname = m;
464 				sbfree(&so->so_rcv, m);
465 if(m->m_next) panic("receive 1b");
466 				so->so_rcv.sb_mb = m = m->m_act;
467 			} else
468 				m = sbdroprecord(&so->so_rcv);
469 		}
470 	}
471 	if (m && m->m_type == MT_RIGHTS) {
472 		if ((pr->pr_flags & PR_RIGHTS) == 0)
473 			panic("receive 2a");
474 		if (flags & MSG_PEEK) {
475 			if (rightsp)
476 				*rightsp = m_copy(m, 0, m->m_len);
477 			else
478 				m = m->m_act;
479 		} else {
480 			if (rightsp) {
481 				*rightsp = m;
482 				sbfree(&so->so_rcv, m);
483 if(m->m_next) panic("receive 2b");
484 				so->so_rcv.sb_mb = m = m->m_act;
485 			} else
486 				m = sbdroprecord(&so->so_rcv);
487 		}
488 	}
489 	if (m == 0 || (m->m_type != MT_DATA && m->m_type != MT_HEADER))
490 		panic("receive 3");
491 	moff = 0;
492 	tomark = so->so_oobmark;
493 	while (m && uio->uio_resid > 0 && error == 0) {
494 		len = uio->uio_resid;
495 		so->so_state &= ~SS_RCVATMARK;
496 		if (tomark && len > tomark)
497 			len = tomark;
498 		if (len > m->m_len - moff)
499 			len = m->m_len - moff;
500 		splx(s);
501 		error =
502 		    uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
503 		s = splnet();
504 		if (len == m->m_len - moff) {
505 			if ((flags & MSG_PEEK) == 0) {
506 				nextrecord = m->m_act;
507 				sbfree(&so->so_rcv, m);
508 				MFREE(m, n);
509 				if (m = n)
510 					m->m_act = nextrecord;
511 				so->so_rcv.sb_mb = m;
512 			} else
513 				m = m->m_next;
514 			moff = 0;
515 		} else {
516 			if (flags & MSG_PEEK)
517 				moff += len;
518 			else {
519 				m->m_off += len;
520 				m->m_len -= len;
521 				so->so_rcv.sb_cc -= len;
522 			}
523 		}
524 		if ((flags & MSG_PEEK) == 0 && so->so_oobmark) {
525 			so->so_oobmark -= len;
526 			if (so->so_oobmark == 0) {
527 				so->so_state |= SS_RCVATMARK;
528 				break;
529 			}
530 		}
531 		if (tomark) {
532 			tomark -= len;
533 			if (tomark == 0)
534 				break;
535 		}
536 	}
537 	if ((flags & MSG_PEEK) == 0) {
538 		if (m == 0)
539 			so->so_rcv.sb_mb = nextrecord;
540 		else if (pr->pr_flags & PR_ATOMIC)
541 			(void) sbdroprecord(&so->so_rcv);
542 		if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
543 			(*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
544 			    (struct mbuf *)0, (struct mbuf *)0);
545 	}
546 release:
547 	sbunlock(&so->so_rcv);
548 	if (error == 0 && rightsp && *rightsp && pr->pr_domain->dom_externalize)
549 		error = (*pr->pr_domain->dom_externalize)(*rightsp);
550 	splx(s);
551 	return (error);
552 }
553 
554 soshutdown(so, how)
555 	register struct socket *so;
556 	register int how;
557 {
558 	register struct protosw *pr = so->so_proto;
559 
560 	how++;
561 	if (how & FREAD)
562 		sorflush(so);
563 	if (how & FWRITE)
564 		return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
565 		    (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
566 	return (0);
567 }
568 
569 sorflush(so)
570 	register struct socket *so;
571 {
572 	register struct sockbuf *sb = &so->so_rcv;
573 	register struct protosw *pr = so->so_proto;
574 	register int s;
575 	struct sockbuf asb;
576 
577 	sblock(sb);
578 	s = splimp();
579 	socantrcvmore(so);
580 	sbunlock(sb);
581 	asb = *sb;
582 	bzero((caddr_t)sb, sizeof (*sb));
583 	splx(s);
584 	if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
585 		(*pr->pr_domain->dom_dispose)(asb.sb_mb);
586 	sbrelease(&asb);
587 }
588 
589 sosetopt(so, level, optname, m0)
590 	register struct socket *so;
591 	int level, optname;
592 	struct mbuf *m0;
593 {
594 	int error = 0;
595 	register struct mbuf *m = m0;
596 
597 	if (level != SOL_SOCKET) {
598 		if (so->so_proto && so->so_proto->pr_ctloutput)
599 			return ((*so->so_proto->pr_ctloutput)
600 				  (PRCO_SETOPT, so, level, optname, &m0));
601 		error = ENOPROTOOPT;
602 	} else {
603 		switch (optname) {
604 
605 		case SO_LINGER:
606 			if (m == NULL || m->m_len != sizeof (struct linger)) {
607 				error = EINVAL;
608 				goto bad;
609 			}
610 			so->so_linger = mtod(m, struct linger *)->l_linger;
611 			/* fall thru... */
612 
613 		case SO_DEBUG:
614 		case SO_KEEPALIVE:
615 		case SO_DONTROUTE:
616 		case SO_USELOOPBACK:
617 		case SO_BROADCAST:
618 		case SO_REUSEADDR:
619 			if (m == NULL || m->m_len < sizeof (int)) {
620 				error = EINVAL;
621 				goto bad;
622 			}
623 			if (*mtod(m, int *))
624 				so->so_options |= optname;
625 			else
626 				so->so_options &= ~optname;
627 			break;
628 
629 		case SO_SNDBUF:
630 		case SO_RCVBUF:
631 		case SO_SNDLOWAT:
632 		case SO_RCVLOWAT:
633 		case SO_SNDTIMEO:
634 		case SO_RCVTIMEO:
635 			if (m == NULL || m->m_len < sizeof (int)) {
636 				error = EINVAL;
637 				goto bad;
638 			}
639 			switch (optname) {
640 
641 			case SO_SNDBUF:
642 			case SO_RCVBUF:
643 				if (sbreserve(optname == SO_SNDBUF ? &so->so_snd :
644 				    &so->so_rcv, *mtod(m, int *)) == 0) {
645 					error = ENOBUFS;
646 					goto bad;
647 				}
648 				break;
649 
650 			case SO_SNDLOWAT:
651 				so->so_snd.sb_lowat = *mtod(m, int *);
652 				break;
653 			case SO_RCVLOWAT:
654 				so->so_rcv.sb_lowat = *mtod(m, int *);
655 				break;
656 			case SO_SNDTIMEO:
657 				so->so_snd.sb_timeo = *mtod(m, int *);
658 				break;
659 			case SO_RCVTIMEO:
660 				so->so_rcv.sb_timeo = *mtod(m, int *);
661 				break;
662 			}
663 			break;
664 
665 		default:
666 			error = ENOPROTOOPT;
667 			break;
668 		}
669 	}
670 bad:
671 	if (m)
672 		(void) m_free(m);
673 	return (error);
674 }
675 
676 sogetopt(so, level, optname, mp)
677 	register struct socket *so;
678 	int level, optname;
679 	struct mbuf **mp;
680 {
681 	register struct mbuf *m;
682 
683 	if (level != SOL_SOCKET) {
684 		if (so->so_proto && so->so_proto->pr_ctloutput) {
685 			return ((*so->so_proto->pr_ctloutput)
686 				  (PRCO_GETOPT, so, level, optname, mp));
687 		} else
688 			return (ENOPROTOOPT);
689 	} else {
690 		m = m_get(M_WAIT, MT_SOOPTS);
691 		switch (optname) {
692 
693 		case SO_LINGER:
694 			m->m_len = sizeof (struct linger);
695 			mtod(m, struct linger *)->l_onoff =
696 				so->so_options & SO_LINGER;
697 			mtod(m, struct linger *)->l_linger = so->so_linger;
698 			break;
699 
700 		case SO_USELOOPBACK:
701 		case SO_DONTROUTE:
702 		case SO_DEBUG:
703 		case SO_KEEPALIVE:
704 		case SO_REUSEADDR:
705 		case SO_BROADCAST:
706 			m->m_len = sizeof (int);
707 			*mtod(m, int *) = so->so_options & optname;
708 			break;
709 
710 		case SO_SNDBUF:
711 			*mtod(m, int *) = so->so_snd.sb_hiwat;
712 			break;
713 
714 		case SO_RCVBUF:
715 			*mtod(m, int *) = so->so_rcv.sb_hiwat;
716 			break;
717 
718 		case SO_SNDLOWAT:
719 			*mtod(m, int *) = so->so_snd.sb_lowat;
720 			break;
721 
722 		case SO_RCVLOWAT:
723 			*mtod(m, int *) = so->so_rcv.sb_lowat;
724 			break;
725 
726 		case SO_SNDTIMEO:
727 			*mtod(m, int *) = so->so_snd.sb_timeo;
728 			break;
729 
730 		case SO_RCVTIMEO:
731 			*mtod(m, int *) = so->so_rcv.sb_timeo;
732 			break;
733 
734 		default:
735 			m_free(m);
736 			return (ENOPROTOOPT);
737 		}
738 		*mp = m;
739 		return (0);
740 	}
741 }
742 
743 sohasoutofband(so)
744 	register struct socket *so;
745 {
746 	struct proc *p;
747 
748 	if (so->so_pgrp < 0)
749 		gsignal(-so->so_pgrp, SIGURG);
750 	else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0)
751 		psignal(p, SIGURG);
752 }
753