summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1998-08-23 03:07:17 +0000
committerwollman <wollman@FreeBSD.org>1998-08-23 03:07:17 +0000
commita76fb5eefabdc9418c911bf0b61768d533c15cbd (patch)
tree02b1e59b8833c25c113cc2a72ebb74ec057423bb /sys/netinet
parent3846bf0ec8c81eca47577791dff72e8b96928749 (diff)
downloadFreeBSD-src-a76fb5eefabdc9418c911bf0b61768d533c15cbd.zip
FreeBSD-src-a76fb5eefabdc9418c911bf0b61768d533c15cbd.tar.gz
Yow! Completely change the way socket options are handled, eliminating
another specialized mbuf type in the process. Also clean up some of the cruft surrounding IPFW, multicast routing, RSVP, and other ill-explored corners.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in.h17
-rw-r--r--sys/netinet/in_proto.c11
-rw-r--r--sys/netinet/ip_fw.c268
-rw-r--r--sys/netinet/ip_fw.h19
-rw-r--r--sys/netinet/ip_input.c7
-rw-r--r--sys/netinet/ip_mroute.c297
-rw-r--r--sys/netinet/ip_mroute.h8
-rw-r--r--sys/netinet/ip_output.c395
-rw-r--r--sys/netinet/ip_var.h14
-rw-r--r--sys/netinet/raw_ip.c190
-rw-r--r--sys/netinet/tcp_usrreq.c117
-rw-r--r--sys/netinet/tcp_var.h5
12 files changed, 684 insertions, 664 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 1450185..67e5851 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
- * $Id: in.h,v 1.35 1998/06/06 20:45:25 julian Exp $
+ * $Id: in.h,v 1.36 1998/07/06 03:20:12 julian Exp $
*/
#ifndef _NETINET_IN_H_
@@ -429,21 +429,6 @@ int in_cksum __P((struct mbuf *, int));
int in_localaddr __P((struct in_addr));
char *inet_ntoa __P((struct in_addr)); /* in libkern */
-/* Firewall hooks */
-struct ip;
-typedef int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, u_int16_t*, struct mbuf**, struct sockaddr_in**));
-typedef int ip_fw_ctl_t __P((int, struct mbuf**));
-extern ip_fw_chk_t *ip_fw_chk_ptr;
-extern ip_fw_ctl_t *ip_fw_ctl_ptr;
-
-/* IP NAT hooks */
-typedef int ip_nat_t __P((struct ip**, struct mbuf**, struct ifnet*, int));
-typedef int ip_nat_ctl_t __P((int, struct mbuf**));
-extern ip_nat_t *ip_nat_ptr;
-extern ip_nat_ctl_t *ip_nat_ctl_ptr;
-#define IP_NAT_IN 0x00000001
-#define IP_NAT_OUT 0x00000002
-
#endif /* KERNEL */
#endif
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index de7d67d..2976056 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in_proto.c 8.2 (Berkeley) 2/9/95
- * $Id: in_proto.c,v 1.45 1997/12/15 20:31:11 eivind Exp $
+ * $Id: in_proto.c,v 1.46 1998/03/21 11:33:57 peter Exp $
*/
#include "opt_ipdivert.h"
@@ -71,15 +71,6 @@
#include <netns/ns_if.h>
#endif
-#ifdef TPIP
-void tpip_input(), tpip_ctlinput(), tp_init(), tp_slowtimo(), tp_drain();
-int tp_ctloutput(), tp_usrreq();
-#endif
-
-#ifdef EON
-void eoninput(), eonctlinput(), eonprotoinit();
-#endif /* EON */
-
extern struct domain inetdomain;
static struct pr_usrreqs nousrreqs;
diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c
index 5ef7ec6..6376389 100644
--- a/sys/netinet/ip_fw.c
+++ b/sys/netinet/ip_fw.c
@@ -12,7 +12,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.c,v 1.94 1998/08/03 17:23:37 dfr Exp $
+ * $Id: ip_fw.c,v 1.95 1998/08/11 19:08:42 bde Exp $
*/
/*
@@ -34,6 +34,7 @@
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -60,6 +61,8 @@ static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
static int fw_verbose_limit = 0;
#endif
+#define IPFW_DEFAULT_RULE ((u_int)(u_short)~0)
+
static LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
static MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
@@ -83,9 +86,8 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_lim
static int add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl));
static int del_entry __P((struct ip_fw_head *chainptr, u_short number));
-static int zero_entry __P((struct mbuf *m));
-static struct ip_fw *check_ipfw_struct __P((struct ip_fw *m));
-static struct ip_fw *check_ipfw_mbuf __P((struct mbuf *fw));
+static int zero_entry __P((struct ip_fw *));
+static int check_ipfw_struct __P((struct ip_fw *m));
static __inline int
iface_match __P((struct ifnet *ifp, union ip_fw_if *ifu,
int byname));
@@ -106,7 +108,7 @@ static ip_fw_ctl_t *old_ctl_ptr;
static int ip_fw_chk __P((struct ip **pip, int hlen,
struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
struct sockaddr_in **next_hop));
-static int ip_fw_ctl __P((int stage, struct mbuf **mm));
+static int ip_fw_ctl __P((struct sockopt *sopt));
static char err_prefix[] = "ip_fw_ctl:";
@@ -424,7 +426,7 @@ ip_fw_chk(struct ip **pip, int hlen,
*/
chain = LIST_FIRST(&ip_fw_chain);
if ( skipto ) {
- if (skipto >= 65535)
+ if (skipto >= IPFW_DEFAULT_RULE)
goto dropit;
while (chain && (chain->rule->fw_number <= skipto)) {
chain = LIST_NEXT(chain, chain);
@@ -645,7 +647,7 @@ got_match:
}
#ifdef DIAGNOSTIC
- /* Rule 65535 should always be there and should always match */
+ /* Rule IPFW_DEFAULT_RULE should always be there and should always match */
if (!chain)
panic("ip_fw: chain");
#endif
@@ -734,16 +736,10 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
s = splnet();
- if (!LIST_FIRST(chainptr)) {
+ if (chainptr->lh_first == 0) {
LIST_INSERT_HEAD(chainptr, fwc, chain);
splx(s);
return(0);
- } else if (ftmp->fw_number == (u_short)-1) {
- if (fwc) free(fwc, M_IPFW);
- if (ftmp) free(ftmp, M_IPFW);
- splx(s);
- dprintf(("%s bad rule number\n", err_prefix));
- return (EINVAL);
}
/* If entry number is 0, find highest numbered rule and add 100 */
@@ -754,7 +750,7 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
else
break;
}
- if (nbr < (u_short)-1 - 100)
+ if (nbr < IPFW_DEFAULT_RULE - 100)
nbr += 100;
ftmp->fw_number = nbr;
}
@@ -809,21 +805,12 @@ del_entry(struct ip_fw_head *chainptr, u_short number)
}
static int
-zero_entry(struct mbuf *m)
+zero_entry(struct ip_fw *frwl)
{
- struct ip_fw *frwl;
struct ip_fw_chain *fcp;
- int s;
-
- if (m) {
- if (m->m_len != sizeof(struct ip_fw))
- return(EINVAL);
- frwl = mtod(m, struct ip_fw *);
- }
- else
- frwl = NULL;
+ int s, cleared;
- if (!frwl) {
+ if (frwl == 0) {
s = splnet();
for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) {
fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
@@ -832,7 +819,7 @@ zero_entry(struct mbuf *m)
splx(s);
}
else {
- int cleared = 0;
+ cleared = 0;
/*
* It's possible to insert multiple chain entries with the
@@ -851,8 +838,8 @@ zero_entry(struct mbuf *m)
cleared = 1;
break;
}
- if (!cleared)
- return(EINVAL); /* we didn't find any matching rules */
+ if (!cleared) /* we didn't find any matching rules */
+ return (EINVAL);
}
if (fw_verbose) {
@@ -862,34 +849,22 @@ zero_entry(struct mbuf *m)
printf("ipfw: Accounting cleared.\n");
}
- return(0);
-}
-
-static struct ip_fw *
-check_ipfw_mbuf(struct mbuf *m)
-{
- /* Check length */
- if (m->m_len != sizeof(struct ip_fw)) {
- dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
- sizeof(struct ip_fw)));
- return (NULL);
- }
- return(check_ipfw_struct(mtod(m, struct ip_fw *)));
+ return (0);
}
-static struct ip_fw *
+static int
check_ipfw_struct(struct ip_fw *frwl)
{
/* Check for invalid flag bits */
if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {
dprintf(("%s undefined flag bits set (flags=%x)\n",
err_prefix, frwl->fw_flg));
- return (NULL);
+ return (EINVAL);
}
/* Must apply to incoming or outgoing (or both) */
if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {
dprintf(("%s neither in nor out\n", err_prefix));
- return (NULL);
+ return (EINVAL);
}
/* Empty interface name is no good */
if (((frwl->fw_flg & IP_FW_F_IIFNAME)
@@ -897,7 +872,7 @@ check_ipfw_struct(struct ip_fw *frwl)
|| ((frwl->fw_flg & IP_FW_F_OIFNAME)
&& !*frwl->fw_out_if.fu_via_if.name)) {
dprintf(("%s empty interface name\n", err_prefix));
- return (NULL);
+ return (EINVAL);
}
/* Sanity check interface matching */
if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
@@ -906,23 +881,23 @@ check_ipfw_struct(struct ip_fw *frwl)
&& (frwl->fw_flg & IP_FW_F_OIFACE)) {
dprintf(("%s outgoing interface check on incoming\n",
err_prefix));
- return (NULL);
+ return (EINVAL);
}
/* Sanity check port ranges */
if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {
dprintf(("%s src range set but n_src_p=%d\n",
err_prefix, IP_FW_GETNSRCP(frwl)));
- return (NULL);
+ return (EINVAL);
}
if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {
dprintf(("%s dst range set but n_dst_p=%d\n",
err_prefix, IP_FW_GETNDSTP(frwl)));
- return (NULL);
+ return (EINVAL);
}
if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {
dprintf(("%s too many ports (%d+%d)\n",
err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));
- return (NULL);
+ return (EINVAL);
}
/*
* Protocols other than TCP/UDP don't use port range
@@ -932,7 +907,7 @@ check_ipfw_struct(struct ip_fw *frwl)
(IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {
dprintf(("%s port(s) specified for non TCP/UDP rule\n",
err_prefix));
- return(NULL);
+ return (EINVAL);
}
/*
@@ -943,19 +918,19 @@ check_ipfw_struct(struct ip_fw *frwl)
if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) ||
(frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {
dprintf(("%s rule never matches\n", err_prefix));
- return(NULL);
+ return (EINVAL);
}
if ((frwl->fw_flg & IP_FW_F_FRAG) &&
(frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
if (frwl->fw_nports) {
dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
- return(NULL);
+ return (EINVAL);
}
if (frwl->fw_prot == IPPROTO_TCP &&
frwl->fw_tcpf != frwl->fw_tcpnf) {
dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
- return(NULL);
+ return (EINVAL);
}
}
@@ -967,14 +942,14 @@ check_ipfw_struct(struct ip_fw *frwl)
&& !(frwl->fw_prot == IPPROTO_TCP
&& frwl->fw_reject_code == IP_FW_REJECT_RST)) {
dprintf(("%s unknown reject code\n", err_prefix));
- return(NULL);
+ return (EINVAL);
}
break;
case IP_FW_F_DIVERT: /* Diverting to port zero is invalid */
case IP_FW_F_TEE:
if (frwl->fw_divert_port == 0) {
dprintf(("%s can't divert to port 0\n", err_prefix));
- return (NULL);
+ return (EINVAL);
}
break;
case IP_FW_F_DENY:
@@ -987,117 +962,102 @@ check_ipfw_struct(struct ip_fw *frwl)
break;
default:
dprintf(("%s invalid command\n", err_prefix));
- return(NULL);
+ return (EINVAL);
}
- return frwl;
+ return 0;
}
static int
-ip_fw_ctl(int stage, struct mbuf **mm)
+ip_fw_ctl(struct sockopt *sopt)
{
- int error;
- /*
- * If we have any number of rules, then it's worth while
- * using clusters for this. The smaller case is rare.
- * Note that using clusters for setsockopt is only in 3.0 at this time.
- */
- struct mbuf *m;
-
- if (stage == IP_FW_GET) {
- /*
- * If we have any number of rules, then it's worth while
- * using clusters for this. The smaller case is rare.
- * Note that using clusters for setsockopt is only in
- * 3.0 at this time.
- */
- struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);
- *mm = m = m_get(M_WAIT, MT_SOOPTS);
- if (m == NULL)
- return (ENOBUFS);
- MCLGET(m, M_WAIT);
- if (!(m->m_flags & M_EXT)) {
-abort: m_freem(*mm);
- *mm = NULL;
- return (ENOBUFS);
+ int error, s;
+ size_t size;
+ char *buf, *bp;
+ struct ip_fw_chain *fcp;
+ struct ip_fw frwl;
+
+ /* Disallow sets in really-really secure mode. */
+ if (sopt->sopt_dir == SOPT_SET && securelevel >= 3)
+ return (EPERM);
+ error = 0;
+
+ switch (sopt->sopt_name) {
+ case IP_FW_GET:
+ for (fcp = LIST_FIRST(&ip_fw_chain), size = 0; fcp;
+ fcp = LIST_NEXT(fcp, chain))
+ size += sizeof *fcp->rule;
+ buf = malloc(size, M_TEMP, M_WAITOK);
+ if (buf == 0) {
+ error = ENOBUFS;
+ break;
}
- m->m_len = 0;
- for (; fcp; fcp = LIST_NEXT(fcp, chain)) {
- /* Will we need a new cluster? */
- if ((m->m_len + sizeof *(fcp->rule)) > MCLBYTES) {
- m = m->m_next = m_get(M_WAIT, MT_SOOPTS);
- if (m == NULL) {
- goto abort;
- }
- MCLGET(m, M_WAIT);
- if (!(m->m_flags & M_EXT)) {
- goto abort;
- }
- m->m_len = 0;
- }
- memcpy(m->m_data + m->m_len, fcp->rule,
- sizeof *(fcp->rule));
- m->m_len += sizeof *(fcp->rule);
+
+ for (fcp = LIST_FIRST(&ip_fw_chain), bp = buf; fcp;
+ fcp = LIST_NEXT(fcp, chain)) {
+ bcopy(fcp->rule, bp, sizeof *fcp->rule);
+ bp += sizeof *fcp->rule;
}
- return (0);
- }
- m = *mm;
- /* only allow get calls if secure mode > 2 */
- if (securelevel > 2) {
- if (m) (void)m_free(m);
- return(EPERM);
- }
- if (stage == IP_FW_FLUSH) {
- while (LIST_FIRST(&ip_fw_chain) != NULL &&
- LIST_FIRST(&ip_fw_chain)->rule->fw_number != (u_short)-1) {
- struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);
- int s = splnet();
- LIST_REMOVE(LIST_FIRST(&ip_fw_chain), chain);
+ error = sooptcopyout(sopt, buf, size);
+ FREE(buf, M_TEMP);
+ break;
+
+ case IP_FW_FLUSH:
+ for (fcp = ip_fw_chain.lh_first;
+ fcp != 0 && fcp->rule->fw_number != IPFW_DEFAULT_RULE;
+ fcp = ip_fw_chain.lh_first) {
+ s = splnet();
+ LIST_REMOVE(fcp, chain);
+ FREE(fcp->rule, M_IPFW);
+ FREE(fcp, M_IPFW);
splx(s);
- free(fcp->rule, M_IPFW);
- free(fcp, M_IPFW);
}
- if (m) (void)m_free(m);
- return (0);
- }
- if (stage == IP_FW_ZERO) {
- error = zero_entry(m);
- if (m) (void)m_free(m);
- return (error);
- }
- if (m == NULL) {
- printf("%s NULL mbuf ptr\n", err_prefix);
- return (EINVAL);
- }
+ break;
- if (stage == IP_FW_ADD) {
- struct ip_fw *frwl = check_ipfw_mbuf(m);
+ case IP_FW_ZERO:
+ if (sopt->sopt_val != 0) {
+ error = sooptcopyin(sopt, &frwl, sizeof frwl,
+ sizeof frwl);
+ if (error || (error = zero_entry(&frwl)))
+ break;
+ } else {
+ error = zero_entry(0);
+ }
+ break;
- if (!frwl)
- error = EINVAL;
- else
- error = add_entry(&ip_fw_chain, frwl);
- if (m) (void)m_free(m);
- return error;
- }
- if (stage == IP_FW_DEL) {
- if (m->m_len != sizeof(struct ip_fw)) {
- dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
- sizeof(struct ip_fw)));
+ case IP_FW_ADD:
+ error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
+ if (error || (error = check_ipfw_struct(&frwl)))
+ break;
+
+ if (frwl.fw_number == IPFW_DEFAULT_RULE) {
+ dprintf(("%s can't add rule %u\n", err_prefix,
+ (unsigned)IPFW_DEFAULT_RULE));
error = EINVAL;
- } else if (mtod(m, struct ip_fw *)->fw_number == (u_short)-1) {
- dprintf(("%s can't delete rule 65535\n", err_prefix));
+ } else {
+ error = add_entry(&ip_fw_chain, &frwl);
+ }
+ break;
+
+ case IP_FW_DEL:
+ error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
+ if (error)
+ break;
+
+ if (frwl.fw_number == IPFW_DEFAULT_RULE) {
+ dprintf(("%s can't delete rule %u\n", err_prefix,
+ (unsigned)IPFW_DEFAULT_RULE));
error = EINVAL;
- } else
- error = del_entry(&ip_fw_chain,
- mtod(m, struct ip_fw *)->fw_number);
- if (m) (void)m_free(m);
- return error;
+ } else {
+ error = del_entry(&ip_fw_chain, frwl.fw_number);
+ }
+ break;
+
+ default:
+ panic("ip_fw_ctl");
}
- dprintf(("%s unknown request %d\n", err_prefix, stage));
- if (m) (void)m_free(m);
- return (EINVAL);
+ return (error);
}
void
@@ -1111,14 +1071,14 @@ ip_fw_init(void)
bzero(&default_rule, sizeof default_rule);
default_rule.fw_prot = IPPROTO_IP;
- default_rule.fw_number = (u_short)-1;
+ default_rule.fw_number = IPFW_DEFAULT_RULE;
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
default_rule.fw_flg |= IP_FW_F_ACCEPT;
#else
default_rule.fw_flg |= IP_FW_F_DENY;
#endif
default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
- if (check_ipfw_struct(&default_rule) == NULL ||
+ if (check_ipfw_struct(&default_rule) != 0 ||
add_entry(&ip_fw_chain, &default_rule))
panic("ip_fw_init");
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 572d1b7..d903c57 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -11,7 +11,7 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $Id: ip_fw.h,v 1.32 1998/02/03 22:15:03 bde Exp $
+ * $Id: ip_fw.h,v 1.33 1998/07/06 03:20:15 julian Exp $
*/
#ifndef _IP_FW_H
@@ -184,6 +184,23 @@ struct ip_fw_chain {
*/
void ip_fw_init __P((void));
+/* Firewall hooks */
+struct ip;
+struct sockopt;
+typedef int ip_fw_chk_t __P((struct ip **, int, struct ifnet *, u_int16_t *,
+ struct mbuf **, struct sockaddr_in **));
+typedef int ip_fw_ctl_t __P((struct sockopt *));
+extern ip_fw_chk_t *ip_fw_chk_ptr;
+extern ip_fw_ctl_t *ip_fw_ctl_ptr;
+
+/* IP NAT hooks */
+typedef int ip_nat_t __P((struct ip **, struct mbuf **, struct ifnet *, int));
+typedef int ip_nat_ctl_t __P((struct sockopt *));
+extern ip_nat_t *ip_nat_ptr;
+extern ip_nat_ctl_t *ip_nat_ctl_ptr;
+#define IP_NAT_IN 0x00000001
+#define IP_NAT_OUT 0x00000002
+
#endif /* KERNEL */
#endif /* _IP_FW_H */
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 16d1abd..4527c08 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
- * $Id: ip_input.c,v 1.97 1998/07/13 12:12:24 bde Exp $
+ * $Id: ip_input.c,v 1.98 1998/08/17 01:05:24 bde Exp $
* $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $
*/
@@ -142,6 +142,9 @@ SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW,
#endif
#ifdef COMPAT_IPFW
+
+#include <netinet/ip_fw.h>
+
/* Firewall hooks */
ip_fw_chk_t *ip_fw_chk_ptr;
ip_fw_ctl_t *ip_fw_ctl_ptr;
@@ -1234,7 +1237,7 @@ ip_srcroute()
if (ip_nhops == 0)
return ((struct mbuf *)0);
- m = m_get(M_DONTWAIT, MT_SOOPTS);
+ m = m_get(M_DONTWAIT, MT_HEADER);
if (m == 0)
return ((struct mbuf *)0);
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 1e64bb3..3c11f82 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -9,7 +9,7 @@
* Modified by Bill Fenner, PARC, April 1995
*
* MROUTING Revision: 3.5
- * $Id: ip_mroute.c,v 1.47 1998/06/30 10:56:31 phk Exp $
+ * $Id: ip_mroute.c,v 1.48 1998/08/17 01:05:24 bde Exp $
*/
#include "opt_mrouting.h"
@@ -54,10 +54,8 @@ extern u_long _ip_mcast_src __P((int vifi));
extern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp,
struct mbuf *m, struct ip_moptions *imo));
extern int _ip_mrouter_done __P((void));
-extern int _ip_mrouter_get __P((int cmd, struct socket *so,
- struct mbuf **m));
-extern int _ip_mrouter_set __P((int cmd, struct socket *so,
- struct mbuf *m));
+extern int _ip_mrouter_get __P((struct socket *so, struct sockopt *sopt));
+extern int _ip_mrouter_set __P((struct socket *so, struct sockopt *sopt));
extern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p));
/*
@@ -70,27 +68,25 @@ static struct mrtstat mrtstat;
u_int rsvpdebug = 0;
int
-_ip_mrouter_set(cmd, so, m)
- int cmd;
+_ip_mrouter_set(so, sopt)
struct socket *so;
- struct mbuf *m;
+ struct sockopt *sopt;
{
return(EOPNOTSUPP);
}
-int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set;
+int (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set;
int
-_ip_mrouter_get(cmd, so, m)
- int cmd;
+_ip_mrouter_get(so, sopt)
struct socket *so;
- struct mbuf **m;
+ struct sockopt *sopt;
{
return(EOPNOTSUPP);
}
-int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get;
+int (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get;
int
_ip_mrouter_done()
@@ -161,17 +157,17 @@ _ip_mcast_src(int vifi) { return INADDR_ANY; }
u_long (*ip_mcast_src)(int) = _ip_mcast_src;
int
-ip_rsvp_vif_init(so, m)
+ip_rsvp_vif_init(so, sopt)
struct socket *so;
- struct mbuf *m;
+ struct sockopt *sopt;
{
return(EINVAL);
}
int
-ip_rsvp_vif_done(so, m)
+ip_rsvp_vif_done(so, sopt)
struct socket *so;
- struct mbuf *m;
+ struct sockopt *sopt;
{
return(EINVAL);
}
@@ -279,22 +275,20 @@ static struct vif *last_encap_vif;
static u_long X_ip_mcast_src __P((int vifi));
static int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo));
static int X_ip_mrouter_done __P((void));
-static int X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m));
-static int X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m));
+static int X_ip_mrouter_get __P((struct socket *so, struct sockopt *m));
+static int X_ip_mrouter_set __P((struct socket *so, struct sockopt *m));
static int X_legal_vif_num __P((int vif));
static int X_mrt_ioctl __P((int cmd, caddr_t data));
static int get_sg_cnt(struct sioc_sg_req *);
static int get_vif_cnt(struct sioc_vif_req *);
-static int ip_mrouter_init(struct socket *, struct mbuf *);
+static int ip_mrouter_init(struct socket *, int);
static int add_vif(struct vifctl *);
-static int del_vif(vifi_t *);
+static int del_vif(vifi_t);
static int add_mfc(struct mfcctl *);
static int del_mfc(struct mfcctl *);
static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);
-static int get_version(struct mbuf *);
-static int get_assert(struct mbuf *);
-static int set_assert(int *);
+static int set_assert(int);
static void expire_upcalls(void *);
static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *,
vifi_t);
@@ -386,53 +380,102 @@ static void collate(struct timeval *);
* Handle MRT setsockopt commands to modify the multicast routing tables.
*/
static int
-X_ip_mrouter_set(cmd, so, m)
- int cmd;
- struct socket *so;
- struct mbuf *m;
+X_ip_mrouter_set(so, sopt)
+ struct socket *so;
+ struct sockopt *sopt;
{
- if (cmd != MRT_INIT && so != ip_mrouter) return EACCES;
+ int error, optval;
+ vifi_t vifi;
+ struct vifctl vifc;
+ struct mfcctl mfc;
+
+ if (so != ip_mrouter && sopt->sopt_name != MRT_INIT)
+ return (EPERM);
+
+ error = 0;
+ switch (sopt->sopt_name) {
+ case MRT_INIT:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+ error = ip_mrouter_init(so, optval);
+ break;
- switch (cmd) {
- case MRT_INIT: return ip_mrouter_init(so, m);
- case MRT_DONE: return ip_mrouter_done();
- case MRT_ADD_VIF: return add_vif (mtod(m, struct vifctl *));
- case MRT_DEL_VIF: return del_vif (mtod(m, vifi_t *));
- case MRT_ADD_MFC: return add_mfc (mtod(m, struct mfcctl *));
- case MRT_DEL_MFC: return del_mfc (mtod(m, struct mfcctl *));
- case MRT_ASSERT: return set_assert(mtod(m, int *));
- default: return EOPNOTSUPP;
- }
+ case MRT_DONE:
+ error = ip_mrouter_done();
+ break;
+
+ case MRT_ADD_VIF:
+ error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
+ if (error)
+ break;
+ error = add_vif(&vifc);
+ break;
+
+ case MRT_DEL_VIF:
+ error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
+ if (error)
+ break;
+ error = del_vif(vifi);
+ break;
+
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc);
+ if (error)
+ break;
+ if (sopt->sopt_name == MRT_ADD_MFC)
+ error = add_mfc(&mfc);
+ else
+ error = del_mfc(&mfc);
+
+ case MRT_ASSERT:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+ set_assert(optval);
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return (error);
}
#ifndef MROUTE_LKM
-int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set;
+int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set;
#endif
/*
* Handle MRT getsockopt commands
*/
static int
-X_ip_mrouter_get(cmd, so, m)
- int cmd;
- struct socket *so;
- struct mbuf **m;
+X_ip_mrouter_get(so, sopt)
+ struct socket *so;
+ struct sockopt *sopt;
{
- struct mbuf *mb;
+ int error;
+ static int version = 0x0305; /* !!! why is this here? XXX */
- if (so != ip_mrouter) return EACCES;
+ switch (sopt->sopt_name) {
+ case MRT_VERSION:
+ error = sooptcopyout(sopt, &version, sizeof version);
+ break;
- *m = mb = m_get(M_WAIT, MT_SOOPTS);
-
- switch (cmd) {
- case MRT_VERSION: return get_version(mb);
- case MRT_ASSERT: return get_assert(mb);
- default: return EOPNOTSUPP;
- }
+ case MRT_ASSERT:
+ error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return (error);
}
#ifndef MROUTE_LKM
-int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get;
+int (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get;
#endif
/*
@@ -509,9 +552,9 @@ get_vif_cnt(req)
* Enable multicast routing
*/
static int
-ip_mrouter_init(so, m)
+ip_mrouter_init(so, version)
struct socket *so;
- struct mbuf *m;
+ int version;
{
int *v;
@@ -522,11 +565,7 @@ ip_mrouter_init(so, m)
if (so->so_type != SOCK_RAW ||
so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;
- if (!m || (m->m_len != sizeof(int *)))
- return ENOPROTOOPT;
-
- v = mtod(m, int *);
- if (*v != 1)
+ if (version != 1)
return ENOPROTOOPT;
if (ip_mrouter != NULL) return EADDRINUSE;
@@ -626,47 +665,17 @@ X_ip_mrouter_done()
int (*ip_mrouter_done)(void) = X_ip_mrouter_done;
#endif
-static int
-get_version(mb)
- struct mbuf *mb;
-{
- int *v;
-
- v = mtod(mb, int *);
-
- *v = 0x0305; /* XXX !!!! */
- mb->m_len = sizeof(int);
-
- return 0;
-}
-
/*
* Set PIM assert processing global
*/
static int
set_assert(i)
- int *i;
+ int i;
{
- if ((*i != 1) && (*i != 0))
+ if ((i != 1) && (i != 0))
return EINVAL;
- pim_assert = *i;
-
- return 0;
-}
-
-/*
- * Get PIM assert processing global
- */
-static int
-get_assert(m)
- struct mbuf *m;
-{
- int *i;
-
- i = mtod(m, int *);
-
- *i = pim_assert;
+ pim_assert = i;
return 0;
}
@@ -777,17 +786,16 @@ add_vif(vifcp)
* Delete a vif from the vif table
*/
static int
-del_vif(vifip)
- vifi_t *vifip;
+del_vif(vifi)
+ vifi_t vifi;
{
- register struct vif *vifp = viftable + *vifip;
- register vifi_t vifi;
+ register struct vif *vifp = &viftable[vifi];
register struct mbuf *m;
struct ifnet *ifp;
struct ifreq ifr;
int s;
- if (*vifip >= numvifs) return EINVAL;
+ if (vifi >= numvifs) return EINVAL;
if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL;
s = splnet();
@@ -816,6 +824,9 @@ del_vif(vifip)
bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf)));
bzero((caddr_t)vifp, sizeof (*vifp));
+ if (mrtdebug)
+ log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
+
/* Adjust numvifs down */
for (vifi = numvifs; vifi > 0; vifi--)
if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;
@@ -823,9 +834,6 @@ del_vif(vifip)
splx(s);
- if (mrtdebug)
- log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs);
-
return 0;
}
@@ -2009,12 +2017,11 @@ priority(vifp, ip)
*/
int
-ip_rsvp_vif_init(so, m)
- struct socket *so;
- struct mbuf *m;
+ip_rsvp_vif_init(so, sopt)
+ struct socket *so;
+ struct sockopt *sopt;
{
- int i;
- register int s;
+ int error, i, s;
if (rsvpdebug)
printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",
@@ -2024,13 +2031,12 @@ ip_rsvp_vif_init(so, m)
return EOPNOTSUPP;
/* Check mbuf. */
- if (m == NULL || m->m_len != sizeof(int)) {
- return EINVAL;
- }
- i = *(mtod(m, int *));
+ error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+ if (error)
+ return (error);
if (rsvpdebug)
- printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n",i,rsvp_on);
+ printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on);
s = splnet();
@@ -2060,49 +2066,48 @@ ip_rsvp_vif_init(so, m)
}
int
-ip_rsvp_vif_done(so, m)
- struct socket *so;
- struct mbuf *m;
+ip_rsvp_vif_done(so, sopt)
+ struct socket *so;
+ struct sockopt *sopt;
{
- int i;
- register int s;
+ int error, i, s;
- if (rsvpdebug)
- printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
- so->so_type, so->so_proto->pr_protocol);
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
+ so->so_type, so->so_proto->pr_protocol);
- if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
- return EOPNOTSUPP;
+ if (so->so_type != SOCK_RAW ||
+ so->so_proto->pr_protocol != IPPROTO_RSVP)
+ return EOPNOTSUPP;
- /* Check mbuf. */
- if (m == NULL || m->m_len != sizeof(int)) {
- return EINVAL;
- }
- i = *(mtod(m, int *));
+ error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+ if (error)
+ return (error);
- s = splnet();
+ s = splnet();
- /* Check vif. */
- if (!legal_vif_num(i)) {
- splx(s);
- return EADDRNOTAVAIL;
- }
+ /* Check vif. */
+ if (!legal_vif_num(i)) {
+ splx(s);
+ return EADDRNOTAVAIL;
+ }
- if (rsvpdebug)
- printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
- viftable[i].v_rsvpd, so);
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
+ viftable[i].v_rsvpd, so);
- viftable[i].v_rsvpd = NULL;
- /* This may seem silly, but we need to be sure we don't over-decrement
- * the RSVP counter, in case something slips up.
- */
- if (viftable[i].v_rsvp_on) {
- viftable[i].v_rsvp_on = 0;
- rsvp_on--;
- }
+ viftable[i].v_rsvpd = NULL;
+ /*
+ * This may seem silly, but we need to be sure we don't over-decrement
+ * the RSVP counter, in case something slips up.
+ */
+ if (viftable[i].v_rsvp_on) {
+ viftable[i].v_rsvp_on = 0;
+ rsvp_on--;
+ }
- splx(s);
- return 0;
+ splx(s);
+ return 0;
}
void
diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h
index 5ddd679..94ddeac 100644
--- a/sys/netinet/ip_mroute.h
+++ b/sys/netinet/ip_mroute.h
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)ip_mroute.h 8.1 (Berkeley) 6/10/93
- * $Id$
+ * $Id: ip_mroute.h,v 1.13 1997/02/22 09:41:35 peter Exp $
*/
#ifndef _NETINET_IP_MROUTE_H_
@@ -248,8 +248,10 @@ struct tbf
#ifdef KERNEL
-extern int (*ip_mrouter_set) __P((int, struct socket *, struct mbuf *));
-extern int (*ip_mrouter_get) __P((int, struct socket *, struct mbuf **));
+struct sockopt;
+
+extern int (*ip_mrouter_set) __P((struct socket *, struct sockopt *));
+extern int (*ip_mrouter_get) __P((struct socket *, struct sockopt *));
extern int (*ip_mrouter_done) __P((void));
#ifdef MROUTING
extern int (*mrt_ioctl) __P((int, caddr_t));
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 9202b2f..4e6c646 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
- * $Id: ip_output.c,v 1.79 1998/07/13 12:12:25 bde Exp $
+ * $Id: ip_output.c,v 1.80 1998/08/01 08:44:33 peter Exp $
*/
#define _IP_VHL
@@ -72,6 +72,10 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#undef COMPAT_IPFW
#endif
+#ifdef COMPAT_IPFW
+#include <netinet/ip_fw.h>
+#endif
+
#ifdef IPFIREWALL_FORWARD_DEBUG
#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
(ntohl(a.s_addr)>>16)&0xFF,\
@@ -85,10 +89,10 @@ static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
static void ip_mloopback
__P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
static int ip_getmoptions
- __P((int, struct ip_moptions *, struct mbuf **));
-static int ip_pcbopts __P((struct mbuf **, struct mbuf *));
+ __P((struct sockopt *, struct ip_moptions *));
+static int ip_pcbopts __P((int, struct mbuf **, struct mbuf *));
static int ip_setmoptions
- __P((int, struct ip_moptions **, struct mbuf *));
+ __P((struct sockopt *, struct ip_moptions **));
#if defined(IPFILTER_LKM) || defined(IPFILTER)
int ip_optcopy __P((struct ip *, struct ip *));
@@ -742,33 +746,43 @@ ip_optcopy(ip, jp)
* IP socket option processing.
*/
int
-ip_ctloutput(op, so, level, optname, mp, p)
- int op;
+ip_ctloutput(so, sopt)
struct socket *so;
- int level, optname;
- struct mbuf **mp;
- struct proc *p;
+ struct sockopt *sopt;
{
- register struct inpcb *inp = sotoinpcb(so);
- register struct mbuf *m = *mp;
- register int optval = 0;
- int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ int error, optval;
- if (level != IPPROTO_IP) {
- error = EINVAL;
- if (op == PRCO_SETOPT && *mp)
- (void) m_free(*mp);
- } else switch (op) {
+ error = optval = 0;
+ if (sopt->sopt_level != IPPROTO_IP) {
+ return (EINVAL);
+ }
- case PRCO_SETOPT:
- switch (optname) {
+ switch (sopt->sopt_dir) {
+ case SOPT_SET:
+ switch (sopt->sopt_name) {
case IP_OPTIONS:
#ifdef notyet
case IP_RETOPTS:
- return (ip_pcbopts(optname, &inp->inp_options, m));
-#else
- return (ip_pcbopts(&inp->inp_options, m));
#endif
+ {
+ struct mbuf *m;
+ if (sopt->sopt_valsize > MLEN) {
+ error = EMSGSIZE;
+ break;
+ }
+ MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ error = ENOBUFS;
+ break;
+ }
+ m->m_len = sopt->sopt_valsize;
+ error = sooptcopyin(sopt, mtod(m, char *), m->m_len,
+ m->m_len);
+
+ return (ip_pcbopts(sopt->sopt_name, &inp->inp_options,
+ m));
+ }
case IP_TOS:
case IP_TTL:
@@ -776,41 +790,40 @@ ip_ctloutput(op, so, level, optname, mp, p)
case IP_RECVRETOPTS:
case IP_RECVDSTADDR:
case IP_RECVIF:
- if (m == 0 || m->m_len != sizeof(int))
- error = EINVAL;
- else {
- optval = *mtod(m, int *);
- switch (optname) {
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
- case IP_TOS:
- inp->inp_ip_tos = optval;
- break;
+ switch (sopt->sopt_name) {
+ case IP_TOS:
+ inp->inp_ip_tos = optval;
+ break;
- case IP_TTL:
- inp->inp_ip_ttl = optval;
- break;
+ case IP_TTL:
+ inp->inp_ip_ttl = optval;
+ break;
#define OPTSET(bit) \
if (optval) \
inp->inp_flags |= bit; \
else \
inp->inp_flags &= ~bit;
- case IP_RECVOPTS:
- OPTSET(INP_RECVOPTS);
- break;
+ case IP_RECVOPTS:
+ OPTSET(INP_RECVOPTS);
+ break;
- case IP_RECVRETOPTS:
- OPTSET(INP_RECVRETOPTS);
- break;
+ case IP_RECVRETOPTS:
+ OPTSET(INP_RECVRETOPTS);
+ break;
- case IP_RECVDSTADDR:
- OPTSET(INP_RECVDSTADDR);
- break;
+ case IP_RECVDSTADDR:
+ OPTSET(INP_RECVDSTADDR);
+ break;
- case IP_RECVIF:
- OPTSET(INP_RECVIF);
- break;
- }
+ case IP_RECVIF:
+ OPTSET(INP_RECVIF);
+ break;
}
break;
#undef OPTSET
@@ -821,36 +834,34 @@ ip_ctloutput(op, so, level, optname, mp, p)
case IP_MULTICAST_LOOP:
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
- error = ip_setmoptions(optname, &inp->inp_moptions, m);
+ error = ip_setmoptions(sopt, &inp->inp_moptions);
break;
case IP_PORTRANGE:
- if (m == 0 || m->m_len != sizeof(int))
- error = EINVAL;
- else {
- optval = *mtod(m, int *);
-
- switch (optval) {
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
- case IP_PORTRANGE_DEFAULT:
- inp->inp_flags &= ~(INP_LOWPORT);
- inp->inp_flags &= ~(INP_HIGHPORT);
- break;
+ switch (optval) {
+ case IP_PORTRANGE_DEFAULT:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ break;
- case IP_PORTRANGE_HIGH:
- inp->inp_flags &= ~(INP_LOWPORT);
- inp->inp_flags |= INP_HIGHPORT;
- break;
+ case IP_PORTRANGE_HIGH:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags |= INP_HIGHPORT;
+ break;
- case IP_PORTRANGE_LOW:
- inp->inp_flags &= ~(INP_HIGHPORT);
- inp->inp_flags |= INP_LOWPORT;
- break;
+ case IP_PORTRANGE_LOW:
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ inp->inp_flags |= INP_LOWPORT;
+ break;
- default:
- error = EINVAL;
- break;
- }
+ default:
+ error = EINVAL;
+ break;
}
break;
@@ -858,21 +869,19 @@ ip_ctloutput(op, so, level, optname, mp, p)
error = ENOPROTOOPT;
break;
}
- if (m)
- (void)m_free(m);
break;
- case PRCO_GETOPT:
- switch (optname) {
+ case SOPT_GET:
+ switch (sopt->sopt_name) {
case IP_OPTIONS:
case IP_RETOPTS:
- *mp = m = m_get(M_WAIT, MT_SOOPTS);
- if (inp->inp_options) {
- m->m_len = inp->inp_options->m_len;
- bcopy(mtod(inp->inp_options, void *),
- mtod(m, void *), m->m_len);
- } else
- m->m_len = 0;
+ if (inp->inp_options)
+ error = sooptcopyout(sopt,
+ mtod(inp->inp_options,
+ char *),
+ inp->inp_options->m_len);
+ else
+ sopt->sopt_valsize = 0;
break;
case IP_TOS:
@@ -881,9 +890,8 @@ ip_ctloutput(op, so, level, optname, mp, p)
case IP_RECVRETOPTS:
case IP_RECVDSTADDR:
case IP_RECVIF:
- *mp = m = m_get(M_WAIT, MT_SOOPTS);
- m->m_len = sizeof(int);
- switch (optname) {
+ case IP_PORTRANGE:
+ switch (sopt->sopt_name) {
case IP_TOS:
optval = inp->inp_ip_tos;
@@ -910,8 +918,17 @@ ip_ctloutput(op, so, level, optname, mp, p)
case IP_RECVIF:
optval = OPTBIT(INP_RECVIF);
break;
+
+ case IP_PORTRANGE:
+ if (inp->inp_flags & INP_HIGHPORT)
+ optval = IP_PORTRANGE_HIGH;
+ else if (inp->inp_flags & INP_LOWPORT)
+ optval = IP_PORTRANGE_LOW;
+ else
+ optval = 0;
+ break;
}
- *mtod(m, int *) = optval;
+ error = sooptcopyout(sopt, &optval, sizeof optval);
break;
case IP_MULTICAST_IF:
@@ -920,21 +937,7 @@ ip_ctloutput(op, so, level, optname, mp, p)
case IP_MULTICAST_LOOP:
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
- error = ip_getmoptions(optname, inp->inp_moptions, mp);
- break;
-
- case IP_PORTRANGE:
- *mp = m = m_get(M_WAIT, MT_SOOPTS);
- m->m_len = sizeof(int);
-
- if (inp->inp_flags & INP_HIGHPORT)
- optval = IP_PORTRANGE_HIGH;
- else if (inp->inp_flags & INP_LOWPORT)
- optval = IP_PORTRANGE_LOW;
- else
- optval = 0;
-
- *mtod(m, int *) = optval;
+ error = ip_getmoptions(sopt, inp->inp_moptions);
break;
default:
@@ -952,12 +955,8 @@ ip_ctloutput(op, so, level, optname, mp, p)
* with destination address if source routed.
*/
static int
-#ifdef notyet
ip_pcbopts(optname, pcbopt, m)
int optname;
-#else
-ip_pcbopts(pcbopt, m)
-#endif
struct mbuf **pcbopt;
register struct mbuf *m;
{
@@ -1054,23 +1053,28 @@ bad:
}
/*
+ * XXX
+ * The whole multicast option thing needs to be re-thought.
+ * Several of these options are equally applicable to non-multicast
+ * transmission, and one (IP_MULTICAST_TTL) totally duplicates a
+ * standard option (IP_TTL).
+ */
+/*
* Set the IP multicast options in response to user setsockopt().
*/
static int
-ip_setmoptions(optname, imop, m)
- int optname;
+ip_setmoptions(sopt, imop)
+ struct sockopt *sopt;
struct ip_moptions **imop;
- struct mbuf *m;
{
- register int error = 0;
- u_char loop;
- register int i;
+ int error = 0;
+ int i;
struct in_addr addr;
- register struct ip_mreq *mreq;
- register struct ifnet *ifp;
- register struct ip_moptions *imo = *imop;
+ struct ip_mreq mreq;
+ struct ifnet *ifp;
+ struct ip_moptions *imo = *imop;
struct route ro;
- register struct sockaddr_in *dst;
+ struct sockaddr_in *dst;
int s;
if (imo == NULL) {
@@ -1091,18 +1095,16 @@ ip_setmoptions(optname, imop, m)
imo->imo_num_memberships = 0;
}
- switch (optname) {
+ switch (sopt->sopt_name) {
/* store an index number for the vif you wanna use in the send */
case IP_MULTICAST_VIF:
- if (!legal_vif_num) {
+ if (legal_vif_num == 0) {
error = EOPNOTSUPP;
break;
}
- if (m == NULL || m->m_len != sizeof(int)) {
- error = EINVAL;
+ error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+ if (error)
break;
- }
- i = *(mtod(m, int *));
if (!legal_vif_num(i) && (i != -1)) {
error = EINVAL;
break;
@@ -1114,11 +1116,9 @@ ip_setmoptions(optname, imop, m)
/*
* Select the interface for outgoing multicast packets.
*/
- if (m == NULL || m->m_len != sizeof(struct in_addr)) {
- error = EINVAL;
+ error = sooptcopyin(sopt, &addr, sizeof addr, sizeof addr);
+ if (error)
break;
- }
- addr = *(mtod(m, struct in_addr *));
/*
* INADDR_ANY is used to remove a previous selection.
* When no interface is selected, a default one is
@@ -1147,25 +1147,50 @@ ip_setmoptions(optname, imop, m)
case IP_MULTICAST_TTL:
/*
* Set the IP time-to-live for outgoing multicast packets.
+ * The original multicast API required a char argument,
+ * which is inconsistent with the rest of the socket API.
+ * We allow either a char or an int.
*/
- if (m == NULL || m->m_len != 1) {
- error = EINVAL;
- break;
+ if (sopt->sopt_valsize == 1) {
+ u_char ttl;
+ error = sooptcopyin(sopt, &ttl, 1, 1);
+ if (error)
+ break;
+ imo->imo_multicast_ttl = ttl;
+ } else {
+ u_int ttl;
+ error = sooptcopyin(sopt, &ttl, sizeof ttl,
+ sizeof ttl);
+ if (error)
+ break;
+ if (ttl > 255)
+ error = EINVAL;
+ else
+ imo->imo_multicast_ttl = ttl;
}
- imo->imo_multicast_ttl = *(mtod(m, u_char *));
break;
case IP_MULTICAST_LOOP:
/*
* Set the loopback flag for outgoing multicast packets.
- * Must be zero or one.
+ * Must be zero or one. The original multicast API required a
+ * char argument, which is inconsistent with the rest
+ * of the socket API. We allow either a char or an int.
*/
- if (m == NULL || m->m_len != 1 ||
- (loop = *(mtod(m, u_char *))) > 1) {
- error = EINVAL;
- break;
+ if (sopt->sopt_valsize == 1) {
+ u_char loop;
+ error = sooptcopyin(sopt, &loop, 1, 1);
+ if (error)
+ break;
+ imo->imo_multicast_loop = !!loop;
+ } else {
+ u_int loop;
+ error = sooptcopyin(sopt, &loop, sizeof loop,
+ sizeof loop);
+ if (error)
+ break;
+ imo->imo_multicast_loop = !!loop;
}
- imo->imo_multicast_loop = loop;
break;
case IP_ADD_MEMBERSHIP:
@@ -1173,12 +1198,11 @@ ip_setmoptions(optname, imop, m)
* Add a multicast group membership.
* Group must be a valid IP multicast address.
*/
- if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
- error = EINVAL;
+ error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
+ if (error)
break;
- }
- mreq = mtod(m, struct ip_mreq *);
- if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+
+ if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
error = EINVAL;
break;
}
@@ -1187,12 +1211,12 @@ ip_setmoptions(optname, imop, m)
* If no interface address was provided, use the interface of
* the route to the given multicast address.
*/
- if (mreq->imr_interface.s_addr == INADDR_ANY) {
+ if (mreq.imr_interface.s_addr == INADDR_ANY) {
bzero((caddr_t)&ro, sizeof(ro));
dst = (struct sockaddr_in *)&ro.ro_dst;
dst->sin_len = sizeof(*dst);
dst->sin_family = AF_INET;
- dst->sin_addr = mreq->imr_multiaddr;
+ dst->sin_addr = mreq.imr_multiaddr;
rtalloc(&ro);
if (ro.ro_rt == NULL) {
error = EADDRNOTAVAIL;
@@ -1203,7 +1227,7 @@ ip_setmoptions(optname, imop, m)
rtfree(ro.ro_rt);
}
else {
- INADDR_TO_IFP(mreq->imr_interface, ifp);
+ INADDR_TO_IFP(mreq.imr_interface, ifp);
}
/*
@@ -1222,7 +1246,7 @@ ip_setmoptions(optname, imop, m)
for (i = 0; i < imo->imo_num_memberships; ++i) {
if (imo->imo_membership[i]->inm_ifp == ifp &&
imo->imo_membership[i]->inm_addr.s_addr
- == mreq->imr_multiaddr.s_addr)
+ == mreq.imr_multiaddr.s_addr)
break;
}
if (i < imo->imo_num_memberships) {
@@ -1240,7 +1264,7 @@ ip_setmoptions(optname, imop, m)
* address list for the given interface.
*/
if ((imo->imo_membership[i] =
- in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
+ in_addmulti(&mreq.imr_multiaddr, ifp)) == NULL) {
error = ENOBUFS;
splx(s);
break;
@@ -1254,12 +1278,11 @@ ip_setmoptions(optname, imop, m)
* Drop a multicast group membership.
* Group must be a valid IP multicast address.
*/
- if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
- error = EINVAL;
+ error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
+ if (error)
break;
- }
- mreq = mtod(m, struct ip_mreq *);
- if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+
+ if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
error = EINVAL;
break;
}
@@ -1269,10 +1292,10 @@ ip_setmoptions(optname, imop, m)
* If an interface address was specified, get a pointer
* to its ifnet structure.
*/
- if (mreq->imr_interface.s_addr == INADDR_ANY)
+ if (mreq.imr_interface.s_addr == INADDR_ANY)
ifp = NULL;
else {
- INADDR_TO_IFP(mreq->imr_interface, ifp);
+ INADDR_TO_IFP(mreq.imr_interface, ifp);
if (ifp == NULL) {
error = EADDRNOTAVAIL;
splx(s);
@@ -1286,7 +1309,7 @@ ip_setmoptions(optname, imop, m)
if ((ifp == NULL ||
imo->imo_membership[i]->inm_ifp == ifp) &&
imo->imo_membership[i]->inm_addr.s_addr ==
- mreq->imr_multiaddr.s_addr)
+ mreq.imr_multiaddr.s_addr)
break;
}
if (i == imo->imo_num_memberships) {
@@ -1332,57 +1355,63 @@ ip_setmoptions(optname, imop, m)
* Return the IP multicast options in response to user getsockopt().
*/
static int
-ip_getmoptions(optname, imo, mp)
- int optname;
+ip_getmoptions(sopt, imo)
+ struct sockopt *sopt;
register struct ip_moptions *imo;
- register struct mbuf **mp;
{
- u_char *ttl;
- u_char *loop;
- struct in_addr *addr;
+ struct in_addr addr;
struct in_ifaddr *ia;
+ int error, optval;
+ u_char coptval;
- *mp = m_get(M_WAIT, MT_SOOPTS);
-
- switch (optname) {
-
+ error = 0;
+ switch (sopt->sopt_name) {
case IP_MULTICAST_VIF:
if (imo != NULL)
- *(mtod(*mp, int *)) = imo->imo_multicast_vif;
+ optval = imo->imo_multicast_vif;
else
- *(mtod(*mp, int *)) = -1;
- (*mp)->m_len = sizeof(int);
- return(0);
+ optval = -1;
+ error = sooptcopyout(sopt, &optval, sizeof optval);
+ break;
case IP_MULTICAST_IF:
- addr = mtod(*mp, struct in_addr *);
- (*mp)->m_len = sizeof(struct in_addr);
if (imo == NULL || imo->imo_multicast_ifp == NULL)
- addr->s_addr = INADDR_ANY;
+ addr.s_addr = INADDR_ANY;
else {
IFP_TO_IA(imo->imo_multicast_ifp, ia);
- addr->s_addr = (ia == NULL) ? INADDR_ANY
- : IA_SIN(ia)->sin_addr.s_addr;
+ addr.s_addr = (ia == NULL) ? INADDR_ANY
+ : IA_SIN(ia)->sin_addr.s_addr;
}
- return (0);
+ error = sooptcopyout(sopt, &addr, sizeof addr);
+ break;
case IP_MULTICAST_TTL:
- ttl = mtod(*mp, u_char *);
- (*mp)->m_len = 1;
- *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
- : imo->imo_multicast_ttl;
- return (0);
+ if (imo == 0)
+ optval = coptval = IP_DEFAULT_MULTICAST_TTL;
+ else
+ optval = coptval = imo->imo_multicast_ttl;
+ if (sopt->sopt_valsize == 1)
+ error = sooptcopyout(sopt, &coptval, 1);
+ else
+ error = sooptcopyout(sopt, &optval, sizeof optval);
+ break;
case IP_MULTICAST_LOOP:
- loop = mtod(*mp, u_char *);
- (*mp)->m_len = 1;
- *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
- : imo->imo_multicast_loop;
- return (0);
+ if (imo == 0)
+ optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
+ else
+ optval = coptval = imo->imo_multicast_loop;
+ if (sopt->sopt_valsize == 1)
+ error = sooptcopyout(sopt, &coptval, 1);
+ else
+ error = sooptcopyout(sopt, &optval, sizeof optval);
+ break;
default:
- return (EOPNOTSUPP);
+ error = ENOPROTOOPT;
+ break;
}
+ return (error);
}
/*
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 6e3f7d8..16e66fc 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_var.h 8.2 (Berkeley) 1/9/95
- * $Id: ip_var.h,v 1.42 1998/07/06 03:20:18 julian Exp $
+ * $Id: ip_var.h,v 1.43 1998/07/13 12:20:07 bde Exp $
*/
#ifndef _NETINET_IP_VAR_H_
@@ -160,8 +160,10 @@ struct ipstat {
#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
+struct ip;
struct inpcb;
struct route;
+struct sockopt;
extern struct ipstat ipstat;
extern u_short ip_id; /* ip packet ctr, for ids */
@@ -175,8 +177,7 @@ extern u_long (*ip_mcast_src) __P((int));
extern int rsvp_on;
extern struct pr_usrreqs rip_usrreqs;
-int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
- struct proc *));
+int ip_ctloutput __P((struct socket *, struct sockopt *sopt));
void ip_drain __P((void));
void ip_freemoptions __P((struct ip_moptions *));
void ip_init __P((void));
@@ -190,8 +191,7 @@ void ip_slowtimo __P((void));
struct mbuf *
ip_srcroute __P((void));
void ip_stripoptions __P((struct mbuf *, struct mbuf *));
-int rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
- struct proc *p));
+int rip_ctloutput __P((struct socket *, struct sockopt *));
void rip_ctlinput __P((int, struct sockaddr *, void *));
void rip_init __P((void));
void rip_input __P((struct mbuf *, int));
@@ -200,8 +200,8 @@ void ipip_input __P((struct mbuf *, int));
void rsvp_input __P((struct mbuf *, int));
int ip_rsvp_init __P((struct socket *));
int ip_rsvp_done __P((void));
-int ip_rsvp_vif_init __P((struct socket *, struct mbuf *));
-int ip_rsvp_vif_done __P((struct socket *, struct mbuf *));
+int ip_rsvp_vif_init __P((struct socket *, struct sockopt *));
+int ip_rsvp_vif_done __P((struct socket *, struct sockopt *));
void ip_rsvp_force_done __P((struct socket *));
#ifdef IPDIVERT
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 35f4391..ee05690 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
- * $Id: raw_ip.c,v 1.53 1998/03/28 10:18:24 bde Exp $
+ * $Id: raw_ip.c,v 1.54 1998/05/15 20:11:34 wollman Exp $
*/
#include <sys/param.h>
@@ -225,101 +225,127 @@ rip_output(m, so, dst)
* Raw IP socket option processing.
*/
int
-rip_ctloutput(op, so, level, optname, m, p)
- int op;
+rip_ctloutput(so, sopt)
struct socket *so;
- int level, optname;
- struct mbuf **m;
- struct proc *p;
+ struct sockopt *sopt;
{
- register struct inpcb *inp = sotoinpcb(so);
- register int error;
+ struct inpcb *inp = sotoinpcb(so);
+ int error, optval;
- if (level != IPPROTO_IP) {
- if (op == PRCO_SETOPT && *m)
- (void)m_free(*m);
+ if (sopt->sopt_level != IPPROTO_IP)
return (EINVAL);
- }
- switch (optname) {
+ error = 0;
+
+ switch (sopt->sopt_dir) {
+ case SOPT_GET:
+ switch (sopt->sopt_name) {
+ case IP_HDRINCL:
+ optval = inp->inp_flags & INP_HDRINCL;
+ error = sooptcopyout(sopt, &optval, sizeof optval);
+ break;
+
+#ifdef COMPAT_IPFW
+ case IP_FW_GET:
+ if (ip_fw_ctl_ptr == 0)
+ error = ENOPROTOOPT;
+ else
+ error = ip_fw_ctl_ptr(sopt);
+ break;
+
+ case IP_NAT:
+ if (ip_nat_ctl_ptr == 0)
+ error = ENOPROTOOPT;
+ else
+ error = ip_nat_ctl_ptr(sopt);
+ break;
+#endif /* COMPAT_IPFW */
+
+ case MRT_INIT:
+ case MRT_DONE:
+ case MRT_ADD_VIF:
+ case MRT_DEL_VIF:
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ case MRT_VERSION:
+ case MRT_ASSERT:
+ error = ip_mrouter_get(so, sopt);
+ break;
+
+ default:
+ error = ip_ctloutput(so, sopt);
+ break;
+ }
+ break;
- case IP_HDRINCL:
- error = 0;
- if (op == PRCO_SETOPT) {
- if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
- error = EINVAL;
- else if (*mtod(*m, int *))
+ case SOPT_SET:
+ switch (sopt->sopt_name) {
+ case IP_HDRINCL:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+ if (optval)
inp->inp_flags |= INP_HDRINCL;
else
inp->inp_flags &= ~INP_HDRINCL;
- if (*m)
- (void)m_free(*m);
- } else {
- *m = m_get(M_WAIT, MT_SOOPTS);
- (*m)->m_len = sizeof (int);
- *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
- }
- return (error);
+ break;
#ifdef COMPAT_IPFW
- case IP_FW_GET:
- if (ip_fw_ctl_ptr == NULL || op == PRCO_SETOPT) {
- if (*m) (void)m_free(*m);
- return(EINVAL);
- }
- return (*ip_fw_ctl_ptr)(optname, m);
-
- case IP_FW_ADD:
- case IP_FW_DEL:
- case IP_FW_FLUSH:
- case IP_FW_ZERO:
- if (ip_fw_ctl_ptr == NULL || op != PRCO_SETOPT) {
- if (*m) (void)m_free(*m);
- return(EINVAL);
- }
- return (*ip_fw_ctl_ptr)(optname, m);
+ case IP_FW_ADD:
+ case IP_FW_DEL:
+ case IP_FW_FLUSH:
+ case IP_FW_ZERO:
+ if (ip_fw_ctl_ptr == 0)
+ error = ENOPROTOOPT;
+ else
+ error = ip_fw_ctl_ptr(sopt);
+ break;
- case IP_NAT:
- if (ip_nat_ctl_ptr == NULL) {
- if (*m) (void)m_free(*m);
- return(EINVAL);
+ case IP_NAT:
+ if (ip_nat_ctl_ptr == 0)
+ error = ENOPROTOOPT;
+ else
+ error = ip_nat_ctl_ptr(sopt);
+ break;
+#endif /* COMPAT_IPFW */
+
+ case IP_RSVP_ON:
+ error = ip_rsvp_init(so);
+ break;
+
+ case IP_RSVP_OFF:
+ error = ip_rsvp_done();
+ break;
+
+ /* XXX - should be combined */
+ case IP_RSVP_VIF_ON:
+ error = ip_rsvp_vif_init(so, sopt);
+ break;
+
+ case IP_RSVP_VIF_OFF:
+ error = ip_rsvp_vif_done(so, sopt);
+ break;
+
+ case MRT_INIT:
+ case MRT_DONE:
+ case MRT_ADD_VIF:
+ case MRT_DEL_VIF:
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ case MRT_VERSION:
+ case MRT_ASSERT:
+ error = ip_mrouter_set(so, sopt);
+ break;
+
+ default:
+ error = ip_ctloutput(so, sopt);
+ break;
}
- return (*ip_nat_ctl_ptr)(op, m);
-
-#endif
- case IP_RSVP_ON:
- return ip_rsvp_init(so);
- break;
-
- case IP_RSVP_OFF:
- return ip_rsvp_done();
break;
-
- case IP_RSVP_VIF_ON:
- return ip_rsvp_vif_init(so, *m);
-
- case IP_RSVP_VIF_OFF:
- return ip_rsvp_vif_done(so, *m);
-
- case MRT_INIT:
- case MRT_DONE:
- case MRT_ADD_VIF:
- case MRT_DEL_VIF:
- case MRT_ADD_MFC:
- case MRT_DEL_MFC:
- case MRT_VERSION:
- case MRT_ASSERT:
- if (op == PRCO_SETOPT) {
- error = ip_mrouter_set(optname, so, *m);
- if (*m)
- (void)m_free(*m);
- } else if (op == PRCO_GETOPT) {
- error = ip_mrouter_get(optname, so, m);
- } else
- error = EINVAL;
- return (error);
}
- return (ip_ctloutput(op, so, level, optname, m, p));
+
+ return (error);
}
/*
@@ -340,7 +366,7 @@ rip_ctlinput(cmd, sa, vip)
int err;
int flags;
- switch(cmd) {
+ switch (cmd) {
case PRC_IFDOWN:
for (ia = in_ifaddrhead.tqh_first; ia;
ia = ia->ia_link.tqe_next) {
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index cc94bbb..ba0c012 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
- * $Id: tcp_usrreq.c,v 1.36 1997/12/18 09:50:38 davidg Exp $
+ * $Id: tcp_usrreq.c,v 1.37 1998/01/27 09:15:11 davidg Exp $
*/
#include "opt_tcpdebug.h"
@@ -560,104 +560,107 @@ tcp_connect(tp, nam, p)
return 0;
}
+/*
+ * The new sockopt interface makes it possible for us to block in the
+ * copyin/out step (if we take a page fault). Taking a page fault at
+ * splnet() is probably a Bad Thing. (Since sockets and pcbs both now
+ * use TSM, there probably isn't any need for this function to run at
+ * splnet() any more. This needs more examination.)
+ */
int
-tcp_ctloutput(op, so, level, optname, mp, p)
- int op;
+tcp_ctloutput(so, sopt)
struct socket *so;
- int level, optname;
- struct mbuf **mp;
- struct proc *p;
+ struct sockopt *sopt;
{
- int error = 0, s;
- struct inpcb *inp;
- register struct tcpcb *tp;
- register struct mbuf *m;
- register int i;
+ int error, opt, optval, s;
+ struct inpcb *inp;
+ struct tcpcb *tp;
+ struct mbuf *m;
- s = splnet();
+ error = 0;
+ s = splnet(); /* XXX */
inp = sotoinpcb(so);
if (inp == NULL) {
splx(s);
- if (op == PRCO_SETOPT && *mp)
- (void) m_free(*mp);
return (ECONNRESET);
}
- if (level != IPPROTO_TCP) {
- error = ip_ctloutput(op, so, level, optname, mp, p);
+ if (sopt->sopt_level != IPPROTO_TCP) {
+ error = ip_ctloutput(so, sopt);
splx(s);
return (error);
}
tp = intotcpcb(inp);
- switch (op) {
-
- case PRCO_SETOPT:
- m = *mp;
- switch (optname) {
-
+ switch (sopt->sopt_dir) {
+ case SOPT_SET:
+ switch (sopt->sopt_name) {
case TCP_NODELAY:
- if (m == NULL || m->m_len < sizeof (int))
- error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NODELAY;
+ case TCP_NOOPT:
+ case TCP_NOPUSH:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+
+ switch (sopt->sopt_name) {
+ case TCP_NODELAY:
+ opt = TF_NODELAY;
+ break;
+ case TCP_NOOPT:
+ opt = TF_NOOPT;
+ break;
+ case TCP_NOPUSH:
+ opt = TF_NOPUSH;
+ break;
+ default:
+ opt = 0; /* dead code to fool gcc */
+ break;
+ }
+
+ if (optval)
+ tp->t_flags |= opt;
else
- tp->t_flags &= ~TF_NODELAY;
+ tp->t_flags &= ~opt;
break;
case TCP_MAXSEG:
- if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg)
- tp->t_maxseg = i;
- else
- error = EINVAL;
- break;
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
- case TCP_NOOPT:
- if (m == NULL || m->m_len < sizeof (int))
- error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NOOPT;
+ if (optval > 0 && optval <= tp->t_maxseg)
+ tp->t_maxseg = optval;
else
- tp->t_flags &= ~TF_NOOPT;
- break;
-
- case TCP_NOPUSH:
- if (m == NULL || m->m_len < sizeof (int))
error = EINVAL;
- else if (*mtod(m, int *))
- tp->t_flags |= TF_NOPUSH;
- else
- tp->t_flags &= ~TF_NOPUSH;
break;
default:
error = ENOPROTOOPT;
break;
}
- if (m)
- (void) m_free(m);
break;
- case PRCO_GETOPT:
- *mp = m = m_get(M_WAIT, MT_SOOPTS);
- m->m_len = sizeof(int);
-
- switch (optname) {
+ case SOPT_GET:
+ switch (sopt->sopt_name) {
case TCP_NODELAY:
- *mtod(m, int *) = tp->t_flags & TF_NODELAY;
+ optval = tp->t_flags & TF_NODELAY;
break;
case TCP_MAXSEG:
- *mtod(m, int *) = tp->t_maxseg;
+ optval = tp->t_maxseg;
break;
case TCP_NOOPT:
- *mtod(m, int *) = tp->t_flags & TF_NOOPT;
+ optval = tp->t_flags & TF_NOOPT;
break;
case TCP_NOPUSH:
- *mtod(m, int *) = tp->t_flags & TF_NOPUSH;
+ optval = tp->t_flags & TF_NOPUSH;
break;
default:
error = ENOPROTOOPT;
break;
}
+ if (error == 0)
+ error = sooptcopyout(sopt, &optval, sizeof optval);
break;
}
splx(s);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 48b00b7..15291c2 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_var.h 8.4 (Berkeley) 5/24/95
- * $Id: tcp_var.h,v 1.45 1998/06/27 07:30:45 jhay Exp $
+ * $Id: tcp_var.h,v 1.46 1998/07/13 11:09:52 bde Exp $
*/
#ifndef _NETINET_TCP_VAR_H_
@@ -344,8 +344,7 @@ void tcp_canceltimers __P((struct tcpcb *));
struct tcpcb *
tcp_close __P((struct tcpcb *));
void tcp_ctlinput __P((int, struct sockaddr *, void *));
-int tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
- struct proc *));
+int tcp_ctloutput __P((struct socket *, struct sockopt *));
struct tcpcb *
tcp_drop __P((struct tcpcb *, int));
void tcp_drain __P((void));
OpenPOWER on IntegriCloud