|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)raw_ip.c 7.8 (Berkeley) 7/25/90
21: */
22:
23: #include "param.h"
24: #include "malloc.h"
25: #include "mbuf.h"
26: #include "socket.h"
27: #include "protosw.h"
28: #include "socketvar.h"
29: #include "errno.h"
30:
31: #include "../net/if.h"
32: #include "../net/route.h"
33: #include "../net/raw_cb.h"
34:
35: #include "in.h"
36: #include "in_systm.h"
37: #include "ip.h"
38: #include "ip_var.h"
39: #include "in_pcb.h"
40:
41: /*
42: * Raw interface to IP protocol.
43: */
44:
45: struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET };
46: struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
47: struct sockproto ripproto = { PF_INET };
48: /*
49: * Setup generic address and protocol structures
50: * for raw_input routine, then pass them along with
51: * mbuf chain.
52: */
53: rip_input(m)
54: struct mbuf *m;
55: {
56: register struct ip *ip = mtod(m, struct ip *);
57:
58: ripproto.sp_protocol = ip->ip_p;
59: ripdst.sin_addr = ip->ip_dst;
60: ripsrc.sin_addr = ip->ip_src;
61: if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc,
62: (struct sockaddr *)&ripdst) == 0) {
63: ipstat.ips_noproto++;
64: ipstat.ips_delivered--;
65: }
66: }
67:
68: /*
69: * Generate IP header and pass packet to ip_output.
70: * Tack on options user may have setup with control call.
71: */
72: #define satosin(sa) ((struct sockaddr_in *)(sa))
73: rip_output(m, so)
74: register struct mbuf *m;
75: struct socket *so;
76: {
77: register struct ip *ip;
78: register struct raw_inpcb *rp = sotorawinpcb(so);
79: register struct sockaddr_in *sin;
80:
81: /*
82: * If the user handed us a complete IP packet, use it.
83: * Otherwise, allocate an mbuf for a header and fill it in.
84: */
85: if (rp->rinp_flags & RINPF_HDRINCL)
86: ip = mtod(m, struct ip *);
87: else {
88: M_PREPEND(m, sizeof(struct ip), M_WAIT);
89: ip = mtod(m, struct ip *);
90: ip->ip_tos = 0;
91: ip->ip_off = 0;
92: ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol;
93: ip->ip_len = m->m_pkthdr.len;
94: if (sin = satosin(rp->rinp_rcb.rcb_laddr)) {
95: ip->ip_src = sin->sin_addr;
96: } else
97: ip->ip_src.s_addr = 0;
98: if (sin = satosin(rp->rinp_rcb.rcb_faddr))
99: ip->ip_dst = sin->sin_addr;
100: ip->ip_ttl = MAXTTL;
101: }
102: return (ip_output(m,
103: (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options,
104: &rp->rinp_route,
105: (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
106: }
107:
108: /*
109: * Raw IP socket option processing.
110: */
111: rip_ctloutput(op, so, level, optname, m)
112: int op;
113: struct socket *so;
114: int level, optname;
115: struct mbuf **m;
116: {
117: int error = 0;
118: register struct raw_inpcb *rp = sotorawinpcb(so);
119:
120: if (level != IPPROTO_IP)
121: error = EINVAL;
122: else switch (op) {
123:
124: case PRCO_SETOPT:
125: switch (optname) {
126:
127: case IP_OPTIONS:
128: return (ip_pcbopts(&rp->rinp_options, *m));
129:
130: case IP_HDRINCL:
131: if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) {
132: error = EINVAL;
133: break;
134: }
135: if (*mtod(*m, int *))
136: rp->rinp_flags |= RINPF_HDRINCL;
137: else
138: rp->rinp_flags &= ~RINPF_HDRINCL;
139: break;
140:
141: default:
142: error = EINVAL;
143: break;
144: }
145: break;
146:
147: case PRCO_GETOPT:
148: *m = m_get(M_WAIT, MT_SOOPTS);
149: switch (optname) {
150:
151: case IP_OPTIONS:
152: if (rp->rinp_options) {
153: (*m)->m_len = rp->rinp_options->m_len;
154: bcopy(mtod(rp->rinp_options, caddr_t),
155: mtod(*m, caddr_t), (unsigned)(*m)->m_len);
156: } else
157: (*m)->m_len = 0;
158: break;
159:
160: case IP_HDRINCL:
161: (*m)->m_len = sizeof (int);
162: *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL;
163: break;
164:
165: default:
166: error = EINVAL;
167: m_freem(*m);
168: *m = 0;
169: break;
170: }
171: break;
172: }
173: if (op == PRCO_SETOPT && *m)
174: (void)m_free(*m);
175: return (error);
176: }
177:
178: /*ARGSUSED*/
179: rip_usrreq(so, req, m, nam, rights, control)
180: register struct socket *so;
181: int req;
182: struct mbuf *m, *nam, *rights, *control;
183: {
184: register int error = 0;
185: register struct raw_inpcb *rp = sotorawinpcb(so);
186:
187: switch (req) {
188:
189: case PRU_ATTACH:
190: if (rp)
191: panic("rip_attach");
192: MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK);
193: if (rp == 0)
194: return (ENOBUFS);
195: bzero((caddr_t)rp, sizeof *rp);
196: so->so_pcb = (caddr_t)rp;
197: break;
198:
199: case PRU_DETACH:
200: if (rp == 0)
201: panic("rip_detach");
202: if (rp->rinp_options)
203: m_freem(rp->rinp_options);
204: if (rp->rinp_route.ro_rt)
205: RTFREE(rp->rinp_route.ro_rt);
206: if (rp->rinp_rcb.rcb_laddr)
207: rp->rinp_rcb.rcb_laddr = 0;
208: break;
209:
210: case PRU_BIND:
211: {
212: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
213:
214: if (nam->m_len != sizeof(*addr))
215: return (EINVAL);
216: if ((ifnet == 0) ||
217: ((addr->sin_family != AF_INET) &&
218: (addr->sin_family != AF_IMPLINK)) ||
219: (addr->sin_addr.s_addr &&
220: ifa_ifwithaddr((struct sockaddr *)addr) == 0))
221: return (EADDRNOTAVAIL);
222: rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr;
223: rp->rinp_laddr = *addr;
224: return (0);
225: }
226: case PRU_CONNECT:
227: {
228: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
229:
230: if (nam->m_len != sizeof(*addr))
231: return (EINVAL);
232: if (ifnet == 0)
233: return (EADDRNOTAVAIL);
234: if ((addr->sin_family != AF_INET) &&
235: (addr->sin_family != AF_IMPLINK))
236: return (EAFNOSUPPORT);
237: rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr;
238: rp->rinp_faddr = *addr;
239: soisconnected(so);
240: return (0);
241: }
242: }
243: error = raw_usrreq(so, req, m, nam, rights, control);
244:
245: if (error && (req == PRU_ATTACH) && so->so_pcb)
246: free(so->so_pcb, M_PCB);
247: return (error);
248: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.