1*25202Skarels /*	udp_usrreq.c	4.45	83/02/16	*/
2*25202Skarels /*
3*25202Skarels  * UDP protocol implementation.
4*25202Skarels  * Per RFC 768, August, 1980.
5*25202Skarels  */
6*25202Skarels 
7*25202Skarels #include "../h/param.h"
8*25202Skarels #include "../h/dir.h"
9*25202Skarels #include "../h/user.h"
10*25202Skarels #include "../h/mbuf.h"
11*25202Skarels #include "../h/protosw.h"
12*25202Skarels #include "../h/socket.h"
13*25202Skarels #include "../h/socketvar.h"
14*25202Skarels #include "../h/errno.h"
15*25202Skarels 
16*25202Skarels #include "../net/if.h"
17*25202Skarels #include "../net/route.h"
18*25202Skarels 
19*25202Skarels #include "../bbnnet/in.h"
20*25202Skarels #include "../bbnnet/in_var.h"
21*25202Skarels #include "../bbnnet/net.h"
22*25202Skarels #include "../bbnnet/in_pcb.h"
23*25202Skarels #include "../bbnnet/ip.h"
24*25202Skarels #include "../bbnnet/udp.h"
25*25202Skarels #include "../bbnnet/fsm.h"
26*25202Skarels #include "../bbnnet/tcp.h"
27*25202Skarels #include "../bbnnet/icmp.h"
28*25202Skarels 
29*25202Skarels extern udp_binding_used();
30*25202Skarels extern struct inpcb udp;
31*25202Skarels 
32*25202Skarels struct pr_advice udp_advice =
33*25202Skarels {
34*25202Skarels     UDP_RESERVED,		/* all basically the same as TCP */
35*25202Skarels     UDP_USERRESERVED,
36*25202Skarels     UDP_MAXPORT,
37*25202Skarels     UDP_USERRESERVED+1,
38*25202Skarels     sizeof(u_short),
39*25202Skarels     udp_binding_used
40*25202Skarels } ;
41*25202Skarels 
udp_init()42*25202Skarels udp_init()
43*25202Skarels {
44*25202Skarels     udp.inp_next = udp.inp_prev = &udp;
45*25202Skarels     ipsw[IPPROTO_UDP].ipsw_hlen = sizeof(struct udp);
46*25202Skarels }
47*25202Skarels 
48*25202Skarels udp_abort(inp)
49*25202Skarels struct inpcb *inp;
50*25202Skarels {
51*25202Skarels     struct socket *so = inp->inp_socket;
52*25202Skarels 
53*25202Skarels     in_pcbdisconnect(inp, (int(*)())0);
54*25202Skarels     soisdisconnected(so);
55*25202Skarels }
56*25202Skarels 
57*25202Skarels /*
58*25202Skarels  * Is a udp port/address pair already in use?
59*25202Skarels  */
udp_binding_used(inp,lport,lsaddr,reuselocal)60*25202Skarels int udp_binding_used(inp, lport, lsaddr, reuselocal)
61*25202Skarels struct inpcb   *inp;
62*25202Skarels u_short	lport;
63*25202Skarels u_long	lsaddr;
64*25202Skarels {
65*25202Skarels     register struct inpcb *i;
66*25202Skarels 
67*25202Skarels     if (reuselocal)
68*25202Skarels 	/*
69*25202Skarels 	 * But since UDP, unlike TCP, is not connection oriented,
70*25202Skarels 	 * this allows for liars to exist.
71*25202Skarels 	 */
72*25202Skarels 	return (0);
73*25202Skarels 
74*25202Skarels     for (i = udp.inp_next; i != &udp; i = i->inp_next)
75*25202Skarels     {
76*25202Skarels 	if (i != inp)
77*25202Skarels 	    if (i->inp_lport == lport)
78*25202Skarels 		if ((i->inp_laddr.s_addr == lsaddr) ||
79*25202Skarels 		    (i->inp_laddr.s_addr == INADDR_ANY) ||
80*25202Skarels 		    (lsaddr == INADDR_ANY))
81*25202Skarels 			break;
82*25202Skarels     }
83*25202Skarels     return (i != &udp);
84*25202Skarels }
85*25202Skarels 
udp_conn_used(inp,lport,lsaddr,fport,fsaddr)86*25202Skarels char *udp_conn_used(inp, lport, lsaddr, fport, fsaddr)
87*25202Skarels struct inpcb   *inp;
88*25202Skarels u_short	lport;
89*25202Skarels u_long	lsaddr;
90*25202Skarels u_short	fport;
91*25202Skarels u_long	fsaddr;
92*25202Skarels {
93*25202Skarels     register struct inpcb *i;
94*25202Skarels 
95*25202Skarels     for (i = udp.inp_next; i != &udp; i = i->inp_next)
96*25202Skarels     {
97*25202Skarels 	/*
98*25202Skarels 	 * Since our inpcb is in this linked list, don't want to know
99*25202Skarels 	 * if we, ourselves, are already using this connetion.
100*25202Skarels 	 */
101*25202Skarels 	if (i != inp)
102*25202Skarels 	    if ((i->inp_lport == lport) && (i->inp_fport == fport) &&
103*25202Skarels 		(i->inp_laddr.s_addr == lsaddr) &&
104*25202Skarels 		(i->inp_faddr.s_addr == fsaddr))
105*25202Skarels 		    return((char *) i);
106*25202Skarels     }
107*25202Skarels 
108*25202Skarels     return ((char *) NULL);
109*25202Skarels }
110*25202Skarels 
111*25202Skarels 
112*25202Skarels /*ARGSUSED*/
113*25202Skarels udp_usrreq(so, req, m, nam, rights)
114*25202Skarels struct socket *so;
115*25202Skarels register int req;
116*25202Skarels struct mbuf *m, *nam, *rights;
117*25202Skarels {
118*25202Skarels     register int s;
119*25202Skarels     struct inpcb *inp;
120*25202Skarels     int error = 0;
121*25202Skarels 
122*25202Skarels     s = splnet();
123*25202Skarels     inp = sotoinpcb(so);
124*25202Skarels 
125*25202Skarels     if (rights && req != PRU_CONTROL)
126*25202Skarels     {
127*25202Skarels 	if (rights->m_len)
128*25202Skarels 	{
129*25202Skarels 	    error = EINVAL;
130*25202Skarels 	    goto release;
131*25202Skarels 	}
132*25202Skarels     }
133*25202Skarels 
134*25202Skarels     if (inp == NULL && req != PRU_ATTACH)
135*25202Skarels     {
136*25202Skarels 	error = EINVAL;
137*25202Skarels 	goto release;
138*25202Skarels     }
139*25202Skarels 
140*25202Skarels     switch (req)
141*25202Skarels     {
142*25202Skarels 
143*25202Skarels       case PRU_ATTACH:
144*25202Skarels 	if (inp != NULL)
145*25202Skarels 	{
146*25202Skarels 	    error = EINVAL;
147*25202Skarels 	    break;
148*25202Skarels 	}
149*25202Skarels 	error = soreserve(so, 2048, 2048);
150*25202Skarels 	if (error)
151*25202Skarels 	    break;
152*25202Skarels 	error = in_pcballoc(so, &udp);
153*25202Skarels 	if (error)
154*25202Skarels 	    break;
155*25202Skarels 	break;
156*25202Skarels 
157*25202Skarels       case PRU_DETACH:
158*25202Skarels 	if (inp == NULL)
159*25202Skarels 	{
160*25202Skarels 	    error = ENOTCONN;
161*25202Skarels 	    break;
162*25202Skarels 	}
163*25202Skarels 	in_pcbdetach(inp, (int (*)())0);
164*25202Skarels 	break;
165*25202Skarels 
166*25202Skarels       case PRU_BIND:
167*25202Skarels 	error = in_pcbbind(inp, nam, &udp_advice);
168*25202Skarels 	break;
169*25202Skarels 
170*25202Skarels       case PRU_LISTEN:
171*25202Skarels 	error = EOPNOTSUPP;
172*25202Skarels 	break;
173*25202Skarels 
174*25202Skarels       case PRU_CONNECT:
175*25202Skarels 	if (inp->inp_faddr.s_addr != INADDR_ANY)
176*25202Skarels 	{
177*25202Skarels 	    error = EISCONN;
178*25202Skarels 	    break;
179*25202Skarels 	}
180*25202Skarels 	if (inp->inp_lport == 0)
181*25202Skarels 	{
182*25202Skarels 	    error = in_pcbbind(inp, (struct mbuf *)0, &udp_advice);
183*25202Skarels 	    if (error)
184*25202Skarels 		break;
185*25202Skarels 	}
186*25202Skarels 	error = in_pcbconnect(inp, nam, udp_conn_used);
187*25202Skarels 	if (error == 0)
188*25202Skarels 	    soisconnected(so);
189*25202Skarels 	break;
190*25202Skarels 
191*25202Skarels       case PRU_ACCEPT:
192*25202Skarels 	error = EOPNOTSUPP;
193*25202Skarels 	break;
194*25202Skarels 
195*25202Skarels       case PRU_DISCONNECT:
196*25202Skarels 	if (inp->inp_faddr.s_addr == INADDR_ANY)
197*25202Skarels 	{
198*25202Skarels 	    error = ENOTCONN;
199*25202Skarels 	    break;
200*25202Skarels 	}
201*25202Skarels 	in_pcbdisconnect(inp, (int(*)())0);
202*25202Skarels 	soisdisconnected(so);
203*25202Skarels 	break;
204*25202Skarels 
205*25202Skarels       case PRU_SHUTDOWN:
206*25202Skarels 	socantsendmore(so);
207*25202Skarels 	break;
208*25202Skarels 
209*25202Skarels       case PRU_SEND:
210*25202Skarels 	{
211*25202Skarels 	    struct in_addr laddr;
212*25202Skarels 
213*25202Skarels 	    if (nam)
214*25202Skarels 	    {
215*25202Skarels 		laddr = inp->inp_laddr;
216*25202Skarels 		if (inp->inp_faddr.s_addr != INADDR_ANY)
217*25202Skarels 		{
218*25202Skarels 		    error = EISCONN;
219*25202Skarels 		    break;
220*25202Skarels 		}
221*25202Skarels 		if (inp->inp_lport == 0)
222*25202Skarels 		{
223*25202Skarels 		    if (error = in_pcbbind(inp, (struct mbuf *)0, &udp_advice))
224*25202Skarels 			break;
225*25202Skarels 		}
226*25202Skarels 		error = in_pcbconnect(inp, nam, udp_conn_used);
227*25202Skarels 		if (error)
228*25202Skarels 		    break;
229*25202Skarels 	    }
230*25202Skarels 	    else
231*25202Skarels 	    {
232*25202Skarels 		if (inp->inp_faddr.s_addr == INADDR_ANY)
233*25202Skarels 		{
234*25202Skarels 		    error = ENOTCONN;
235*25202Skarels 		    break;
236*25202Skarels 		}
237*25202Skarels 	    }
238*25202Skarels 	    error = udp_output(inp, m);
239*25202Skarels 	    m = NULL;
240*25202Skarels 	    if (nam)
241*25202Skarels 	    {
242*25202Skarels 		in_pcbdisconnect(inp, (int(*))0);
243*25202Skarels 		inp->inp_laddr = laddr;
244*25202Skarels 	    }
245*25202Skarels 	}
246*25202Skarels 	break;
247*25202Skarels 
248*25202Skarels       case PRU_ABORT:
249*25202Skarels 	in_pcbdetach(inp, (int (*)())0);
250*25202Skarels 	break;
251*25202Skarels 
252*25202Skarels       case PRU_CONTROL:
253*25202Skarels 	/* not our ioctl, let lower level try ioctl */
254*25202Skarels 	error = ip_ioctl (inp, (int) m, (caddr_t) nam);
255*25202Skarels 	goto dontfree;
256*25202Skarels 
257*25202Skarels       case PRU_SOCKADDR:
258*25202Skarels 	in_setsockaddr(inp, nam);
259*25202Skarels 	break;
260*25202Skarels 
261*25202Skarels       default:
262*25202Skarels 	panic("udp_usrreq");
263*25202Skarels     }
264*25202Skarels 
265*25202Skarels release :
266*25202Skarels     if (m != NULL)
267*25202Skarels 	m_freem(m);
268*25202Skarels dontfree:
269*25202Skarels     splx(s);
270*25202Skarels     return (error);
271*25202Skarels }
272*25202Skarels 
udp_ctlinput(prc_code,arg)273*25202Skarels udp_ctlinput (prc_code, arg)
274*25202Skarels caddr_t arg;
275*25202Skarels {
276*25202Skarels     int error;
277*25202Skarels 
278*25202Skarels     error = inetctlerrmap[prc_code];
279*25202Skarels 
280*25202Skarels     switch (prc_code)
281*25202Skarels     {
282*25202Skarels 	case PRC_UNREACH_PROTOCOL:	/* icmp message */
283*25202Skarels 	case PRC_UNREACH_PORT:
284*25202Skarels 	case PRC_MSGSIZE:
285*25202Skarels 	    {
286*25202Skarels 	    register struct udp	*up;
287*25202Skarels 	    struct inpcb *inp;
288*25202Skarels 
289*25202Skarels 	    up = (struct udp *) (&((struct icmp *) arg)->ic_iphdr);
290*25202Skarels 	    inp = (struct inpcb *)udp_conn_used ((struct inpcb *) 0,
291*25202Skarels 		up->u_src, up->u_s.s_addr,
292*25202Skarels 		up->u_dst, up->u_d.s_addr);
293*25202Skarels 
294*25202Skarels 	    if (inp)
295*25202Skarels 	    {
296*25202Skarels 		inp->inp_socket->so_error = error;
297*25202Skarels 		udp_abort(inp);
298*25202Skarels 	    }
299*25202Skarels 	    }
300*25202Skarels 	    break;
301*25202Skarels 
302*25202Skarels 	case PRC_UNREACH_NET:
303*25202Skarels 	case PRC_UNREACH_HOST:
304*25202Skarels 	    {
305*25202Skarels 	    register struct udp	*up;
306*25202Skarels 	    struct inpcb *inp;
307*25202Skarels 
308*25202Skarels 	    up = (struct udp *) (&((struct icmp *) arg)->ic_iphdr);
309*25202Skarels 	    inp = (struct inpcb *)udp_conn_used ((struct inpcb *) 0,
310*25202Skarels 		up->u_src, up->u_s.s_addr,
311*25202Skarels 		up->u_dst, up->u_d.s_addr);
312*25202Skarels 
313*25202Skarels 	    if (inp)
314*25202Skarels 	    {
315*25202Skarels 		struct socket *so;
316*25202Skarels 
317*25202Skarels 		so = inp->inp_socket;
318*25202Skarels 		if ((so->so_state & SS_NOFDREF) == 0)
319*25202Skarels 		    advise_user(so, error);
320*25202Skarels 		else
321*25202Skarels 		{
322*25202Skarels 		    so->so_error = error;
323*25202Skarels 		    udp_abort(inp);
324*25202Skarels 		}
325*25202Skarels 	    }
326*25202Skarels 	    }
327*25202Skarels 	    break;
328*25202Skarels 
329*25202Skarels 	case PRC_GWDOWN:
330*25202Skarels 	    in_gdown (&udp, (u_long) arg);
331*25202Skarels 	    break;
332*25202Skarels 
333*25202Skarels 	case PRC_REDIRECT_NET:	/* icmp message */
334*25202Skarels 	case PRC_REDIRECT_HOST:
335*25202Skarels 	    {
336*25202Skarels 	    register struct udp	*up;
337*25202Skarels 	    struct inpcb *inp;
338*25202Skarels 
339*25202Skarels 	    up = (struct udp *) (&((struct icmp *) arg)->ic_iphdr);
340*25202Skarels 	    inp = (struct inpcb *)udp_conn_used ((struct inpcb *) 0,
341*25202Skarels 		up->u_src, up->u_s.s_addr,
342*25202Skarels 		up->u_dst, up->u_d.s_addr);
343*25202Skarels 
344*25202Skarels 	    if (inp)
345*25202Skarels 		icmp_redirect_inp(inp, (struct icmp *) arg,
346*25202Skarels 		 prc_code == PRC_REDIRECT_NET ? rtnet : rthost);
347*25202Skarels 	    }
348*25202Skarels 	    break;
349*25202Skarels 
350*25202Skarels 	case PRC_TIMXCEED_INTRANS:	/* icmp message */
351*25202Skarels 	case PRC_TIMXCEED_REASS:
352*25202Skarels 	case PRC_PARAMPROB:
353*25202Skarels 	case PRC_QUENCH:
354*25202Skarels 	    break;
355*25202Skarels 
356*25202Skarels 	case PRC_IFDOWN:
357*25202Skarels 	    {
358*25202Skarels 	    u_long addr;
359*25202Skarels 
360*25202Skarels 	    addr = ((struct sockaddr_in *)(arg))->sin_addr.s_addr;
361*25202Skarels 	    inpcb_notify(&udp, addr, (u_long) 0, error);
362*25202Skarels 	    inpcb_notify(&udp, (u_long) 0, addr, error);
363*25202Skarels 	    }
364*25202Skarels 	    break;
365*25202Skarels 
366*25202Skarels 	case PRC_HOSTDEAD:	/* from imp interface */
367*25202Skarels 	case PRC_HOSTUNREACH:
368*25202Skarels 	    /*
369*25202Skarels 	     * get same message for destination hosts and gateways.
370*25202Skarels 	     */
371*25202Skarels 	    {
372*25202Skarels 	    u_long addr;
373*25202Skarels 
374*25202Skarels 	    addr = ((struct sockaddr_in *)arg)->sin_addr.s_addr;
375*25202Skarels 	    in_gdown (&udp, addr);
376*25202Skarels 	    inpcb_notify(&udp, (u_long) 0, addr, error);
377*25202Skarels 	    }
378*25202Skarels 	    break;
379*25202Skarels 
380*25202Skarels 	default:
381*25202Skarels 	    panic("udp_ctlinput");
382*25202Skarels     }
383*25202Skarels }
384