1 #ifdef	RCSIDENT
2 static char rcsident[] = "$Header: raw_input.c,v 1.17 85/07/31 09:33:16 walsh Exp $";
3 #endif
4 
5 #include "../h/param.h"
6 #include "../h/dir.h"
7 #include "../h/user.h"
8 #include "../machine/mtpr.h"
9 #include "../h/mbuf.h"
10 #include "../h/socket.h"
11 #include "../h/socketvar.h"
12 
13 #include "../net/if.h"
14 #include "../net/netisr.h"
15 #include "../net/route.h"
16 #include "../net/raw_cb.h"
17 
18 #include "../bbnnet/in.h"
19 #include "../bbnnet/net.h"
20 #include "../bbnnet/in_pcb.h"
21 #include "../bbnnet/in_var.h"
22 #include "../bbnnet/ip.h"
23 #include "../bbnnet/fsm.h"
24 #include "../bbnnet/tcp.h"
25 #include "../bbnnet/icmp.h"
26 #include "../bbnnet/udp.h"
27 #ifdef HMP
28 #include "../bbnnet/hmp.h"
29 #endif HMP
30 #include "../bbnnet/nopcb.h"
31 
32 /*
33  * Sort INET packets for user(s).  To get a packet, socket must match:
34  *
35  *    raw_ip_proto
36  *		domain   (INET)
37  *		protocol (TCP/UDP/ICMP)
38  *    raw_ip_dst
39  *		domain   (INET)
40  *		address, but not port, if connected(2)
41  *    raw_ip_src
42  *		domain   (INET)
43  *		address, but not port, if bound(2)
44  *
45  * Called from ip_input() for packets that were well-formed enough to get
46  * passed up to TCP/UDP/ICMP.
47  */
48 struct	sockaddr_in raw_ip_dst =
49 {
50     AF_INET
51 } ;
52 struct	sockaddr_in raw_ip_src =
53 {
54     AF_INET
55 } ;
56 struct	sockproto raw_ip_proto =
57 {
58     PF_INET
59 } ;
60 
61 raw_ip_input(m)
62 struct mbuf *m;
63 {
64     register struct ip *ip = mtod(m, struct ip *);
65 
66     raw_ip_proto.sp_protocol = ip->ip_p;
67     raw_ip_dst.sin_addr.s_addr = ip->ip_dst.s_addr;
68     raw_ip_src.sin_addr.s_addr = ip->ip_src.s_addr;
69 
70     raw_input (m, &raw_ip_proto, (struct sockaddr *)&raw_ip_src,
71 	(struct sockaddr *)&raw_ip_dst);
72 }
73 
74 /*
75  * Bad ip packets, which are taken care of via calls to ip_log() and netlog().
76  */
77 struct	sockaddr_in netlog_dst =
78 {
79     AF_INET
80 } ;
81 struct	sockaddr_in netlog_src =
82 {
83     AF_INET
84 } ;
85 struct	sockproto netlog_proto =
86 {
87     PF_INET, NETLOG_PROTO
88 } ;
89 
90 netlog(m)
91 struct mbuf *m;
92 {
93     raw_input (m, &netlog_proto, (struct sockaddr *)&netlog_src,
94 	(struct sockaddr *)&netlog_dst);
95 }
96 
97 #ifdef AF_TCPDEBUG
98 	/*
99 	 * TCP debugging log
100 	 *
101 	 * Though the mbuf contains a copy of the tcpcb, and thus a pointer to the
102 	 * inpcb, kernel can't do address sorting since this may point within a freed
103 	 * (and perhaps now recycled) mbuf.  Remember that this logging is done after
104 	 * state changes (closing).
105 	 */
106 	struct	sockaddr_in tcpdebug_dst =
107 	{
108 	    AF_TCPDEBUG
109 	} ;
110 	struct	sockaddr_in tcpdebug_src =
111 	{
112 	    AF_TCPDEBUG
113 	} ;
114 	struct	sockproto tcpdebug_proto =
115 	{
116 	    PF_TCPDEBUG, 0
117 	} ;
118 
119 	tcpdebuglog(m)
120 	struct mbuf *m;
121 	{
122 	    raw_input (m, &tcpdebug_proto, (struct sockaddr *)&tcpdebug_src,
123 		(struct sockaddr *)&tcpdebug_dst);
124 	}
125 #else
126 	tcpdebuglog(m)
127 	struct mbuf *m;
128 	{
129 	    m_freem(m);
130 	}
131 #endif
132 
133 #ifdef AF_RDPDEBUG
134 	struct sockaddr_in rdpdebug_dst =
135 	{
136 	    AF_RDPDEBUG
137 	} ;
138 	struct sockaddr_in rdpdebug_src =
139 	{
140 	    AF_RDPDEBUG
141 	} ;
142 	struct sockproto rdpdebug_proto =
143 	{
144 	    PF_RDPDEBUG, 0
145 	} ;
146 
147 	rdpdebuglog(m)
148 	struct mbuf *m;
149 	{
150 	    raw_input (m, &rdpdebug_proto, (struct sockaddr *)&rdpdebug_src,
151 		(struct sockaddr *)&rdpdebug_dst);
152 	}
153 #else
154 	rdpdebuglog(m)
155 	struct mbuf *m;
156 	{
157 	    m_freem(m);
158 	}
159 #endif
160 
161 
162 struct mbuf *m_bpullup(m0, len)
163 struct mbuf *m0;
164 int len;
165 {
166     register struct mbuf *m, *n;
167     unsigned count;
168 
169     n = m0;
170     if (len > MLEN)
171     {
172 	m_freem(n);
173 	return ((struct mbuf *) NULL);
174     }
175 #ifdef MBUF_DEBUG
176     m = m_get(M_DONTWAIT, n->m_type);
177 #else
178     MGET(m, M_DONTWAIT, n->m_type);
179 #endif
180     if (m == 0)
181     {
182 	m_freem(n);
183 	return ((struct mbuf *) NULL);
184     }
185     m->m_len = 0;
186     m->m_off = MMAXOFF - len;	/* -- difference from m_pullup -- */
187     do
188     {
189 	count = MIN(len, n->m_len);
190 	bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, count);
191 	len -= count;
192 	m->m_len += count;
193 	n->m_off += count;
194 	n->m_len -= count;
195 	if (n->m_len)
196 	    break;
197 	n = m_free(n);
198     }
199     while (n);
200 
201     if (len)
202     {
203 	(void) m_free(m);
204 	m_freem(n);
205 	return ((struct mbuf *) NULL);
206     }
207     m->m_next = n;
208     return (m);
209 }
210 
211 /*
212  * output function called from net/raw_usrreq
213  */
214 
215 /* ARGSUSED */
216 raw_ip_output (m0, so)
217 struct mbuf *m0;
218 struct socket *so;
219 {
220     register struct mbuf	*m;
221     register struct ip 	*ip;
222     register int		 len;
223     int retval;
224 
225     /*
226      * verify length of datagram, get IP header at end of mbuf so can
227      * prepend local net header.
228      */
229     len = 0;
230     for (m = m0 ; m ; m = m->m_next)
231 	len += m->m_len;
232     if (len < sizeof(struct ip))
233     {
234 	m_freem(m0);
235 	return(EMSGSIZE);	/* ### */
236     }
237     if ((m = m_bpullup(m0, sizeof(struct ip))) == NULL)
238 	return (ENOBUFS);
239     ip = mtod(m, struct ip *);
240     if ((ntohs((u_short)ip->ip_len) != len) ||
241 	((ip->ip_hl << IP_HLSHIFT) > len))
242     {
243 	m_freem(m);
244 	return(EMSGSIZE);	/* ### */
245     }
246 
247 #ifdef notdef
248     /* have to be super-user anyway to do this.
249      * Cronus wants to be able to forward broadcast UDP packets.
250      */
251 
252     /*
253      * verify that addresses are valid
254      */
255     if (in_broadcast(ip->ip_src) || (in_iawithaddr(ip->ip_src, TRUE) == 0))
256 #else
257     if (in_broadcast(ip->ip_src))
258 #endif
259     {
260 	m_freem(m);
261 	return (EADDRNOTAVAIL);
262     }
263 
264     NOPCB_IPSEND (m, len, TRUE, retval);
265     return (retval);
266 }
267 
268 
269 
270 /*
271  * Send out an icmp packet.  Use the user's ICMP header, and our own IP
272  * header.
273  */
274 /* ARGSUSED */
275 raw_icmp_output (m0, so)
276 struct mbuf	*m0;
277 struct socket	*so;
278 {
279     register struct mbuf  *m;
280     register struct icmp  *p;
281     register struct ip    *ip;
282     register struct rawcb *rcb;
283     int len;
284     int retval;
285 
286     rcb = sotorawcb(so);
287     if (!(rcb->rcb_flags & RAW_FADDR))
288     {
289 	m_freem(m0);
290 	return(EDESTADDRREQ);
291     }
292 
293     /*
294      * find length of datagram
295      */
296     len = 0;
297     for (m = m0 ; m ; m = m->m_next)
298 	len += m->m_len;
299     if (len < ICMPSIZE)
300     {
301 	m_freem(m0);
302 	return (EMSGSIZE);	/* ### */
303     }
304 
305     /*
306      * Pull up user's ICMP header so we can prepend IP header later.
307      */
308     if ((m = m_bpullup(m0, ICMPSIZE)) == NULL)
309 	return (ENOBUFS);
310 
311     /*
312      * "Verify" ICMP header.  Accept user's type and code.
313      */
314     p = mtod(m, struct icmp *);
315 
316     /*
317      * Use our own checksum, though.  It'll be at least as fast as the
318      * user's and we'll have to use those CPU cycles sometime.
319      */
320     p->ic_sum = 0;
321     p->ic_sum = in_cksum(m, len);
322 
323     /*
324      * Fill in IP header and send it
325      */
326     m->m_off -= sizeof(struct ip);
327     m->m_len += sizeof(struct ip);
328     ip = mtod(m, struct ip *);
329     ip->ip_p	= IPPROTO_ICMP;
330     ip->ip_tos	= 0;
331     ip->ip_dst.s_addr =
332 	((struct sockaddr_in *) &rcb->rcb_faddr)->sin_addr.s_addr;
333 
334     if (rcb->rcb_flags & RAW_LADDR)
335     {
336 	ip->ip_src.s_addr =
337 	    ((struct sockaddr_in *) &rcb->rcb_laddr)->sin_addr.s_addr;
338     }
339     else
340     {
341 	/*
342 	 * We may examine the routing tables twice.
343 	 * perhaps if this gets used a lot, it can be changed.
344 	 */
345 	struct route r;
346 	struct rtentry *rt;
347 
348 	bzero ((caddr_t) &r, sizeof(r));
349 	((struct sockaddr_in *) (&r.ro_dst)) ->sin_family = AF_INET;
350 	((struct sockaddr_in *) (&r.ro_dst)) ->sin_addr.s_addr =
351 	    ip->ip_dst.s_addr;
352 	rtalloc(&r);
353 	if (rt = r.ro_rt)
354 	{
355 	    ip->ip_src = IA_INADDR(in_iafromif(rt->rt_ifp));
356 	    rtfree (rt);
357 	}
358 	else
359 	{
360 	    m_freem(m);
361 	    return (ENETUNREACH);
362 	}
363     }
364 
365     NOPCB_IPSEND (m, len, FALSE, retval);
366     return (retval);
367 }
368 
369 #ifdef NSIP
370 /*
371  * Generate IP header and pass packet to ip_output.
372  * Tack on options user may have setup with control call.
373  */
374 rip_output(m0, so)
375 struct mbuf *m0;
376 struct socket *so;
377 {
378     register struct mbuf *m;
379 
380     /*
381      * get an mbuf for IP header.
382      */
383     m = m_get(M_DONTWAIT, MT_HEADER);
384     if (m == NULL)
385     {
386 	m_freem(m0);
387 	return (ENOBUFS);
388     }
389 
390     /*
391      * Fill in IP header as needed.
392      */
393     m->m_off = MMAXOFF - sizeof(struct ip);
394     m->m_len = sizeof(struct ip);
395     m->m_next = m0;
396     {
397     register struct ip *ip;
398     register struct rawcb *rcb = sotorawcb(so);
399 
400     ip = mtod(m, struct ip *);
401     ip->ip_p	= rcb->rcb_proto.sp_protocol;
402     ip->ip_tos	= 0;
403     ip->ip_dst.s_addr =
404 	((struct sockaddr_in *) &rcb->rcb_faddr)->sin_addr.s_addr;
405     if (rcb->rcb_flags & RAW_LADDR)
406 	ip->ip_src.s_addr =
407 	    ((struct sockaddr_in *) &rcb->rcb_laddr)->sin_addr.s_addr;
408     else
409 	ip->ip_src.s_addr = 0;
410     }
411 
412     {
413     register int retval;
414     register int len;
415 
416     /*
417      * Calculate data length
418      */
419     len = 0;
420     while (m0)
421     {
422 	len += m0->m_len;
423 	m0 = m0->m_next;
424     }
425 
426 
427     NOPCB_IPSEND (m, len, FALSE, retval);
428     return (retval);
429     }
430 }
431 #endif
432 
433 /*
434  * The UDP header is so small and simple, the user should either:
435  *	1.  go all the way and use a raw IP socket
436  * or	2.  use send(2) type system calls.
437  */
438 /* ARGSUSED */
439 raw_udp_output (m0, so)
440 struct mbuf *m0;
441 struct socket *so;
442 {
443     m_freem(m0);
444     return (EOPNOTSUPP);
445 }
446 
447 /*
448  * TCP requires a lot of state information.  Sure we could try to verify the
449  * user's header and pass it on to ip, but unless debugging a new version
450  * in user code with a different protocol number, probably shouldn't ship
451  * out tcp packets, since we'll get packets in reply that might screw us up.
452  *
453  * And how does the sending of a single tcp packet make sense?
454  */
455 /* ARGSUSED */
456 raw_tcp_output (m0, so)
457 struct mbuf *m0;
458 struct socket *so;
459 {
460     m_freem(m0);
461     return (EOPNOTSUPP);
462 }
463 
464 #ifdef RDP
465 /*
466  * ditto TCP for RDP
467  */
468 /* ARGSUSED */
469 raw_rdp_output (m0, so)
470 struct mbuf *m0;
471 struct socket *so;
472 {
473     m_freem(m0);
474     return(EOPNOTSUPP);
475 }
476 #endif
477 
478 /*
479  * use the user level stuff to send -- much simpler
480  */
481 
482 #ifdef HMP
483 /* ARGSUSED */
484 raw_hmp_output (m0, so)
485 struct mbuf *m0;
486 struct socket *so;
487 {
488     m_freem(m0);
489     return(EOPNOTSUPP);
490 }
491 #endif
492