Commit | Line | Data |
---|---|---|
8ae0e4b4 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
8ae0e4b4 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)raw_ip.c 7.1 (Berkeley) %G% |
8ae0e4b4 | 7 | */ |
2a598b25 | 8 | |
20666ad3 JB |
9 | #include "param.h" |
10 | #include "mbuf.h" | |
11 | #include "socket.h" | |
12 | #include "protosw.h" | |
13 | #include "socketvar.h" | |
14 | #include "errno.h" | |
f4d55810 | 15 | |
126472ab | 16 | #include "../net/if.h" |
f4d55810 | 17 | #include "../net/route.h" |
48c8199a | 18 | #include "../net/raw_cb.h" |
f4d55810 | 19 | |
20666ad3 JB |
20 | #include "in.h" |
21 | #include "in_systm.h" | |
22 | #include "ip.h" | |
23 | #include "ip_var.h" | |
2a598b25 BJ |
24 | |
25 | /* | |
94a62155 BJ |
26 | * Raw interface to IP protocol. |
27 | */ | |
28 | ||
48c8199a SL |
29 | struct sockaddr_in ripdst = { AF_INET }; |
30 | struct sockaddr_in ripsrc = { AF_INET }; | |
31 | struct sockproto ripproto = { PF_INET }; | |
94a62155 BJ |
32 | /* |
33 | * Setup generic address and protocol structures | |
34 | * for raw_input routine, then pass them along with | |
35 | * mbuf chain. | |
2a598b25 | 36 | */ |
2a598b25 BJ |
37 | rip_input(m) |
38 | struct mbuf *m; | |
39 | { | |
94a62155 | 40 | register struct ip *ip = mtod(m, struct ip *); |
2a598b25 | 41 | |
94a62155 | 42 | ripproto.sp_protocol = ip->ip_p; |
faad37c0 SL |
43 | ripdst.sin_addr = ip->ip_dst; |
44 | ripsrc.sin_addr = ip->ip_src; | |
02122dcc SL |
45 | raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, |
46 | (struct sockaddr *)&ripdst); | |
2a598b25 BJ |
47 | } |
48 | ||
94a62155 BJ |
49 | /* |
50 | * Generate IP header and pass packet to ip_output. | |
51 | * Tack on options user may have setup with control call. | |
52 | */ | |
53 | rip_output(m0, so) | |
54 | struct mbuf *m0; | |
55 | struct socket *so; | |
2a598b25 | 56 | { |
94a62155 BJ |
57 | register struct mbuf *m; |
58 | register struct ip *ip; | |
126472ab SL |
59 | int len = 0, error; |
60 | struct rawcb *rp = sotorawcb(so); | |
a13c006d | 61 | struct sockaddr_in *sin; |
2a598b25 | 62 | |
94a62155 BJ |
63 | /* |
64 | * Calculate data length and get an mbuf | |
65 | * for IP header. | |
66 | */ | |
67 | for (m = m0; m; m = m->m_next) | |
68 | len += m->m_len; | |
cce93e4b | 69 | m = m_get(M_DONTWAIT, MT_HEADER); |
94a62155 | 70 | if (m == 0) { |
126472ab SL |
71 | error = ENOBUFS; |
72 | goto bad; | |
94a62155 BJ |
73 | } |
74 | ||
75 | /* | |
76 | * Fill in IP header as needed. | |
77 | */ | |
78 | m->m_off = MMAXOFF - sizeof(struct ip); | |
79 | m->m_len = sizeof(struct ip); | |
80 | m->m_next = m0; | |
81 | ip = mtod(m, struct ip *); | |
a8e2e674 | 82 | ip->ip_tos = 0; |
d5645656 | 83 | ip->ip_off = 0; |
f7c8d7b9 | 84 | ip->ip_p = rp->rcb_proto.sp_protocol; |
94a62155 | 85 | ip->ip_len = sizeof(struct ip) + len; |
a13c006d BJ |
86 | if (rp->rcb_flags & RAW_LADDR) { |
87 | sin = (struct sockaddr_in *)&rp->rcb_laddr; | |
88 | if (sin->sin_family != AF_INET) { | |
126472ab SL |
89 | error = EAFNOSUPPORT; |
90 | goto bad; | |
91 | } | |
a13c006d BJ |
92 | ip->ip_src.s_addr = sin->sin_addr.s_addr; |
93 | } else | |
94 | ip->ip_src.s_addr = 0; | |
95 | ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; | |
94a62155 | 96 | ip->ip_ttl = MAXTTL; |
b197d52e MK |
97 | return (ip_output(m, rp->rcb_options, &rp->rcb_route, |
98 | (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); | |
126472ab SL |
99 | bad: |
100 | m_freem(m); | |
101 | return (error); | |
2a598b25 | 102 | } |
b197d52e MK |
103 | |
104 | /* | |
105 | * Raw IP socket option processing. | |
106 | */ | |
107 | rip_ctloutput(op, so, level, optname, m) | |
108 | int op; | |
109 | struct socket *so; | |
110 | int level, optname; | |
111 | struct mbuf **m; | |
112 | { | |
113 | int error = 0; | |
114 | register struct rawcb *rp = sotorawcb(so); | |
115 | ||
116 | if (level != IPPROTO_IP) | |
117 | error = EINVAL; | |
118 | else switch (op) { | |
119 | ||
120 | case PRCO_SETOPT: | |
121 | switch (optname) { | |
122 | case IP_OPTIONS: | |
123 | return (ip_pcbopts(&rp->rcb_options, *m)); | |
124 | ||
125 | default: | |
126 | error = EINVAL; | |
127 | break; | |
128 | } | |
129 | break; | |
130 | ||
131 | case PRCO_GETOPT: | |
132 | switch (optname) { | |
133 | case IP_OPTIONS: | |
134 | *m = m_get(M_WAIT, MT_SOOPTS); | |
135 | if (rp->rcb_options) { | |
136 | (*m)->m_off = rp->rcb_options->m_off; | |
137 | (*m)->m_len = rp->rcb_options->m_len; | |
138 | bcopy(mtod(rp->rcb_options, caddr_t), | |
8011f5df | 139 | mtod(*m, caddr_t), (unsigned)(*m)->m_len); |
b197d52e MK |
140 | } else |
141 | (*m)->m_len = 0; | |
142 | break; | |
143 | default: | |
144 | error = EINVAL; | |
145 | break; | |
146 | } | |
147 | break; | |
148 | } | |
149 | if (op == PRCO_SETOPT) | |
8011f5df | 150 | (void)m_free(*m); |
b197d52e MK |
151 | return (error); |
152 | } |