Commit | Line | Data |
---|---|---|
8ae0e4b4 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
2b6b6284 | 3 | * All rights reserved. |
8ae0e4b4 | 4 | * |
2b6b6284 | 5 | * Redistribution and use in source and binary forms are permitted |
616d42db KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
2b6b6284 | 16 | * |
616d42db | 17 | * @(#)raw_ip.c 7.4 (Berkeley) %G% |
8ae0e4b4 | 18 | */ |
2a598b25 | 19 | |
20666ad3 JB |
20 | #include "param.h" |
21 | #include "mbuf.h" | |
22 | #include "socket.h" | |
23 | #include "protosw.h" | |
24 | #include "socketvar.h" | |
25 | #include "errno.h" | |
f4d55810 | 26 | |
126472ab | 27 | #include "../net/if.h" |
f4d55810 | 28 | #include "../net/route.h" |
48c8199a | 29 | #include "../net/raw_cb.h" |
f4d55810 | 30 | |
20666ad3 JB |
31 | #include "in.h" |
32 | #include "in_systm.h" | |
33 | #include "ip.h" | |
34 | #include "ip_var.h" | |
2a598b25 BJ |
35 | |
36 | /* | |
94a62155 BJ |
37 | * Raw interface to IP protocol. |
38 | */ | |
39 | ||
48c8199a SL |
40 | struct sockaddr_in ripdst = { AF_INET }; |
41 | struct sockaddr_in ripsrc = { AF_INET }; | |
42 | struct sockproto ripproto = { PF_INET }; | |
94a62155 BJ |
43 | /* |
44 | * Setup generic address and protocol structures | |
45 | * for raw_input routine, then pass them along with | |
46 | * mbuf chain. | |
2a598b25 | 47 | */ |
2a598b25 BJ |
48 | rip_input(m) |
49 | struct mbuf *m; | |
50 | { | |
94a62155 | 51 | register struct ip *ip = mtod(m, struct ip *); |
2a598b25 | 52 | |
94a62155 | 53 | ripproto.sp_protocol = ip->ip_p; |
faad37c0 SL |
54 | ripdst.sin_addr = ip->ip_dst; |
55 | ripsrc.sin_addr = ip->ip_src; | |
02122dcc SL |
56 | raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, |
57 | (struct sockaddr *)&ripdst); | |
2a598b25 BJ |
58 | } |
59 | ||
94a62155 BJ |
60 | /* |
61 | * Generate IP header and pass packet to ip_output. | |
62 | * Tack on options user may have setup with control call. | |
63 | */ | |
64 | rip_output(m0, so) | |
65 | struct mbuf *m0; | |
66 | struct socket *so; | |
2a598b25 | 67 | { |
94a62155 BJ |
68 | register struct mbuf *m; |
69 | register struct ip *ip; | |
126472ab SL |
70 | int len = 0, error; |
71 | struct rawcb *rp = sotorawcb(so); | |
a13c006d | 72 | struct sockaddr_in *sin; |
2a598b25 | 73 | |
94a62155 BJ |
74 | /* |
75 | * Calculate data length and get an mbuf | |
76 | * for IP header. | |
77 | */ | |
78 | for (m = m0; m; m = m->m_next) | |
79 | len += m->m_len; | |
cce93e4b | 80 | m = m_get(M_DONTWAIT, MT_HEADER); |
94a62155 | 81 | if (m == 0) { |
126472ab SL |
82 | error = ENOBUFS; |
83 | goto bad; | |
94a62155 BJ |
84 | } |
85 | ||
86 | /* | |
87 | * Fill in IP header as needed. | |
88 | */ | |
89 | m->m_off = MMAXOFF - sizeof(struct ip); | |
90 | m->m_len = sizeof(struct ip); | |
91 | m->m_next = m0; | |
92 | ip = mtod(m, struct ip *); | |
a8e2e674 | 93 | ip->ip_tos = 0; |
d5645656 | 94 | ip->ip_off = 0; |
f7c8d7b9 | 95 | ip->ip_p = rp->rcb_proto.sp_protocol; |
94a62155 | 96 | ip->ip_len = sizeof(struct ip) + len; |
a13c006d BJ |
97 | if (rp->rcb_flags & RAW_LADDR) { |
98 | sin = (struct sockaddr_in *)&rp->rcb_laddr; | |
99 | if (sin->sin_family != AF_INET) { | |
126472ab SL |
100 | error = EAFNOSUPPORT; |
101 | goto bad; | |
102 | } | |
a13c006d BJ |
103 | ip->ip_src.s_addr = sin->sin_addr.s_addr; |
104 | } else | |
105 | ip->ip_src.s_addr = 0; | |
106 | ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; | |
94a62155 | 107 | ip->ip_ttl = MAXTTL; |
b197d52e MK |
108 | return (ip_output(m, rp->rcb_options, &rp->rcb_route, |
109 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); | |
126472ab SL |
110 | bad: |
111 | m_freem(m); | |
112 | return (error); | |
2a598b25 | 113 | } |
b197d52e MK |
114 | |
115 | /* | |
116 | * Raw IP socket option processing. | |
117 | */ | |
118 | rip_ctloutput(op, so, level, optname, m) | |
119 | int op; | |
120 | struct socket *so; | |
121 | int level, optname; | |
122 | struct mbuf **m; | |
123 | { | |
124 | int error = 0; | |
125 | register struct rawcb *rp = sotorawcb(so); | |
126 | ||
127 | if (level != IPPROTO_IP) | |
128 | error = EINVAL; | |
129 | else switch (op) { | |
130 | ||
131 | case PRCO_SETOPT: | |
132 | switch (optname) { | |
133 | case IP_OPTIONS: | |
134 | return (ip_pcbopts(&rp->rcb_options, *m)); | |
135 | ||
136 | default: | |
137 | error = EINVAL; | |
138 | break; | |
139 | } | |
140 | break; | |
141 | ||
142 | case PRCO_GETOPT: | |
143 | switch (optname) { | |
144 | case IP_OPTIONS: | |
145 | *m = m_get(M_WAIT, MT_SOOPTS); | |
146 | if (rp->rcb_options) { | |
147 | (*m)->m_off = rp->rcb_options->m_off; | |
148 | (*m)->m_len = rp->rcb_options->m_len; | |
149 | bcopy(mtod(rp->rcb_options, caddr_t), | |
8011f5df | 150 | mtod(*m, caddr_t), (unsigned)(*m)->m_len); |
b197d52e MK |
151 | } else |
152 | (*m)->m_len = 0; | |
153 | break; | |
154 | default: | |
155 | error = EINVAL; | |
156 | break; | |
157 | } | |
158 | break; | |
159 | } | |
85b035eb | 160 | if (op == PRCO_SETOPT && *m) |
8011f5df | 161 | (void)m_free(*m); |
b197d52e MK |
162 | return (error); |
163 | } |