summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
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