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