date and time created 88/12/14 15:30:09 by sklower
[unix-history] / usr / src / sys / netinet / raw_ip.c
CommitLineData
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
40struct sockaddr_in ripdst = { AF_INET };
41struct sockaddr_in ripsrc = { AF_INET };
42struct 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
48rip_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 */
64rip_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
110bad:
111 m_freem(m);
112 return (error);
2a598b25 113}
b197d52e
MK
114
115/*
116 * Raw IP socket option processing.
117 */
118rip_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}