Deleted Added
full compact
ip_output.c (37996) ip_output.c (38482)
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34 * $Id: ip_output.c,v 1.79 1998/07/13 12:12:25 bde Exp $
34 * $Id: ip_output.c,v 1.80 1998/08/01 08:44:33 peter Exp $
35 */
36
37#define _IP_VHL
38
39#include "opt_ipfw.h"
40#include "opt_ipdivert.h"
41#include "opt_ipfilter.h"
42

--- 24 unchanged lines hidden (view full) ---

67
68#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
69#undef COMPAT_IPFW
70#define COMPAT_IPFW 1
71#else
72#undef COMPAT_IPFW
73#endif
74
35 */
36
37#define _IP_VHL
38
39#include "opt_ipfw.h"
40#include "opt_ipdivert.h"
41#include "opt_ipfilter.h"
42

--- 24 unchanged lines hidden (view full) ---

67
68#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
69#undef COMPAT_IPFW
70#define COMPAT_IPFW 1
71#else
72#undef COMPAT_IPFW
73#endif
74
75#ifdef COMPAT_IPFW
76#include <netinet/ip_fw.h>
77#endif
78
75#ifdef IPFIREWALL_FORWARD_DEBUG
76#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
77 (ntohl(a.s_addr)>>16)&0xFF,\
78 (ntohl(a.s_addr)>>8)&0xFF,\
79 (ntohl(a.s_addr))&0xFF);
80#endif
81
82u_short ip_id;
83
84static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
85static void ip_mloopback
86 __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
87static int ip_getmoptions
79#ifdef IPFIREWALL_FORWARD_DEBUG
80#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
81 (ntohl(a.s_addr)>>16)&0xFF,\
82 (ntohl(a.s_addr)>>8)&0xFF,\
83 (ntohl(a.s_addr))&0xFF);
84#endif
85
86u_short ip_id;
87
88static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
89static void ip_mloopback
90 __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
91static int ip_getmoptions
88 __P((int, struct ip_moptions *, struct mbuf **));
89static int ip_pcbopts __P((struct mbuf **, struct mbuf *));
92 __P((struct sockopt *, struct ip_moptions *));
93static int ip_pcbopts __P((int, struct mbuf **, struct mbuf *));
90static int ip_setmoptions
94static int ip_setmoptions
91 __P((int, struct ip_moptions **, struct mbuf *));
95 __P((struct sockopt *, struct ip_moptions **));
92
93#if defined(IPFILTER_LKM) || defined(IPFILTER)
94int ip_optcopy __P((struct ip *, struct ip *));
95extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
96#else
97static int ip_optcopy __P((struct ip *, struct ip *));
98#endif
99

--- 637 unchanged lines hidden (view full) ---

737 *dp++ = IPOPT_EOL;
738 return (optlen);
739}
740
741/*
742 * IP socket option processing.
743 */
744int
96
97#if defined(IPFILTER_LKM) || defined(IPFILTER)
98int ip_optcopy __P((struct ip *, struct ip *));
99extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
100#else
101static int ip_optcopy __P((struct ip *, struct ip *));
102#endif
103

--- 637 unchanged lines hidden (view full) ---

741 *dp++ = IPOPT_EOL;
742 return (optlen);
743}
744
745/*
746 * IP socket option processing.
747 */
748int
745ip_ctloutput(op, so, level, optname, mp, p)
746 int op;
749ip_ctloutput(so, sopt)
747 struct socket *so;
750 struct socket *so;
748 int level, optname;
749 struct mbuf **mp;
750 struct proc *p;
751 struct sockopt *sopt;
751{
752{
752 register struct inpcb *inp = sotoinpcb(so);
753 register struct mbuf *m = *mp;
754 register int optval = 0;
755 int error = 0;
753 struct inpcb *inp = sotoinpcb(so);
754 int error, optval;
756
755
757 if (level != IPPROTO_IP) {
758 error = EINVAL;
759 if (op == PRCO_SETOPT && *mp)
760 (void) m_free(*mp);
761 } else switch (op) {
756 error = optval = 0;
757 if (sopt->sopt_level != IPPROTO_IP) {
758 return (EINVAL);
759 }
762
760
763 case PRCO_SETOPT:
764 switch (optname) {
761 switch (sopt->sopt_dir) {
762 case SOPT_SET:
763 switch (sopt->sopt_name) {
765 case IP_OPTIONS:
766#ifdef notyet
767 case IP_RETOPTS:
764 case IP_OPTIONS:
765#ifdef notyet
766 case IP_RETOPTS:
768 return (ip_pcbopts(optname, &inp->inp_options, m));
769#else
770 return (ip_pcbopts(&inp->inp_options, m));
771#endif
767#endif
768 {
769 struct mbuf *m;
770 if (sopt->sopt_valsize > MLEN) {
771 error = EMSGSIZE;
772 break;
773 }
774 MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_HEADER);
775 if (m == 0) {
776 error = ENOBUFS;
777 break;
778 }
779 m->m_len = sopt->sopt_valsize;
780 error = sooptcopyin(sopt, mtod(m, char *), m->m_len,
781 m->m_len);
782
783 return (ip_pcbopts(sopt->sopt_name, &inp->inp_options,
784 m));
785 }
772
773 case IP_TOS:
774 case IP_TTL:
775 case IP_RECVOPTS:
776 case IP_RECVRETOPTS:
777 case IP_RECVDSTADDR:
778 case IP_RECVIF:
786
787 case IP_TOS:
788 case IP_TTL:
789 case IP_RECVOPTS:
790 case IP_RECVRETOPTS:
791 case IP_RECVDSTADDR:
792 case IP_RECVIF:
779 if (m == 0 || m->m_len != sizeof(int))
780 error = EINVAL;
781 else {
782 optval = *mtod(m, int *);
783 switch (optname) {
793 error = sooptcopyin(sopt, &optval, sizeof optval,
794 sizeof optval);
795 if (error)
796 break;
784
797
785 case IP_TOS:
786 inp->inp_ip_tos = optval;
787 break;
798 switch (sopt->sopt_name) {
799 case IP_TOS:
800 inp->inp_ip_tos = optval;
801 break;
788
802
789 case IP_TTL:
790 inp->inp_ip_ttl = optval;
791 break;
803 case IP_TTL:
804 inp->inp_ip_ttl = optval;
805 break;
792#define OPTSET(bit) \
793 if (optval) \
794 inp->inp_flags |= bit; \
795 else \
796 inp->inp_flags &= ~bit;
797
806#define OPTSET(bit) \
807 if (optval) \
808 inp->inp_flags |= bit; \
809 else \
810 inp->inp_flags &= ~bit;
811
798 case IP_RECVOPTS:
799 OPTSET(INP_RECVOPTS);
800 break;
812 case IP_RECVOPTS:
813 OPTSET(INP_RECVOPTS);
814 break;
801
815
802 case IP_RECVRETOPTS:
803 OPTSET(INP_RECVRETOPTS);
804 break;
816 case IP_RECVRETOPTS:
817 OPTSET(INP_RECVRETOPTS);
818 break;
805
819
806 case IP_RECVDSTADDR:
807 OPTSET(INP_RECVDSTADDR);
808 break;
820 case IP_RECVDSTADDR:
821 OPTSET(INP_RECVDSTADDR);
822 break;
809
823
810 case IP_RECVIF:
811 OPTSET(INP_RECVIF);
812 break;
813 }
824 case IP_RECVIF:
825 OPTSET(INP_RECVIF);
826 break;
814 }
815 break;
816#undef OPTSET
817
818 case IP_MULTICAST_IF:
819 case IP_MULTICAST_VIF:
820 case IP_MULTICAST_TTL:
821 case IP_MULTICAST_LOOP:
822 case IP_ADD_MEMBERSHIP:
823 case IP_DROP_MEMBERSHIP:
827 }
828 break;
829#undef OPTSET
830
831 case IP_MULTICAST_IF:
832 case IP_MULTICAST_VIF:
833 case IP_MULTICAST_TTL:
834 case IP_MULTICAST_LOOP:
835 case IP_ADD_MEMBERSHIP:
836 case IP_DROP_MEMBERSHIP:
824 error = ip_setmoptions(optname, &inp->inp_moptions, m);
837 error = ip_setmoptions(sopt, &inp->inp_moptions);
825 break;
826
827 case IP_PORTRANGE:
838 break;
839
840 case IP_PORTRANGE:
828 if (m == 0 || m->m_len != sizeof(int))
829 error = EINVAL;
830 else {
831 optval = *mtod(m, int *);
841 error = sooptcopyin(sopt, &optval, sizeof optval,
842 sizeof optval);
843 if (error)
844 break;
832
845
833 switch (optval) {
846 switch (optval) {
847 case IP_PORTRANGE_DEFAULT:
848 inp->inp_flags &= ~(INP_LOWPORT);
849 inp->inp_flags &= ~(INP_HIGHPORT);
850 break;
834
851
835 case IP_PORTRANGE_DEFAULT:
836 inp->inp_flags &= ~(INP_LOWPORT);
837 inp->inp_flags &= ~(INP_HIGHPORT);
838 break;
852 case IP_PORTRANGE_HIGH:
853 inp->inp_flags &= ~(INP_LOWPORT);
854 inp->inp_flags |= INP_HIGHPORT;
855 break;
839
856
840 case IP_PORTRANGE_HIGH:
841 inp->inp_flags &= ~(INP_LOWPORT);
842 inp->inp_flags |= INP_HIGHPORT;
843 break;
857 case IP_PORTRANGE_LOW:
858 inp->inp_flags &= ~(INP_HIGHPORT);
859 inp->inp_flags |= INP_LOWPORT;
860 break;
844
861
845 case IP_PORTRANGE_LOW:
846 inp->inp_flags &= ~(INP_HIGHPORT);
847 inp->inp_flags |= INP_LOWPORT;
848 break;
849
850 default:
851 error = EINVAL;
852 break;
853 }
862 default:
863 error = EINVAL;
864 break;
854 }
855 break;
856
857 default:
858 error = ENOPROTOOPT;
859 break;
860 }
865 }
866 break;
867
868 default:
869 error = ENOPROTOOPT;
870 break;
871 }
861 if (m)
862 (void)m_free(m);
863 break;
864
872 break;
873
865 case PRCO_GETOPT:
866 switch (optname) {
874 case SOPT_GET:
875 switch (sopt->sopt_name) {
867 case IP_OPTIONS:
868 case IP_RETOPTS:
876 case IP_OPTIONS:
877 case IP_RETOPTS:
869 *mp = m = m_get(M_WAIT, MT_SOOPTS);
870 if (inp->inp_options) {
871 m->m_len = inp->inp_options->m_len;
872 bcopy(mtod(inp->inp_options, void *),
873 mtod(m, void *), m->m_len);
874 } else
875 m->m_len = 0;
878 if (inp->inp_options)
879 error = sooptcopyout(sopt,
880 mtod(inp->inp_options,
881 char *),
882 inp->inp_options->m_len);
883 else
884 sopt->sopt_valsize = 0;
876 break;
877
878 case IP_TOS:
879 case IP_TTL:
880 case IP_RECVOPTS:
881 case IP_RECVRETOPTS:
882 case IP_RECVDSTADDR:
883 case IP_RECVIF:
885 break;
886
887 case IP_TOS:
888 case IP_TTL:
889 case IP_RECVOPTS:
890 case IP_RECVRETOPTS:
891 case IP_RECVDSTADDR:
892 case IP_RECVIF:
884 *mp = m = m_get(M_WAIT, MT_SOOPTS);
885 m->m_len = sizeof(int);
886 switch (optname) {
893 case IP_PORTRANGE:
894 switch (sopt->sopt_name) {
887
888 case IP_TOS:
889 optval = inp->inp_ip_tos;
890 break;
891
892 case IP_TTL:
893 optval = inp->inp_ip_ttl;
894 break;

--- 10 unchanged lines hidden (view full) ---

905
906 case IP_RECVDSTADDR:
907 optval = OPTBIT(INP_RECVDSTADDR);
908 break;
909
910 case IP_RECVIF:
911 optval = OPTBIT(INP_RECVIF);
912 break;
895
896 case IP_TOS:
897 optval = inp->inp_ip_tos;
898 break;
899
900 case IP_TTL:
901 optval = inp->inp_ip_ttl;
902 break;

--- 10 unchanged lines hidden (view full) ---

913
914 case IP_RECVDSTADDR:
915 optval = OPTBIT(INP_RECVDSTADDR);
916 break;
917
918 case IP_RECVIF:
919 optval = OPTBIT(INP_RECVIF);
920 break;
921
922 case IP_PORTRANGE:
923 if (inp->inp_flags & INP_HIGHPORT)
924 optval = IP_PORTRANGE_HIGH;
925 else if (inp->inp_flags & INP_LOWPORT)
926 optval = IP_PORTRANGE_LOW;
927 else
928 optval = 0;
929 break;
913 }
930 }
914 *mtod(m, int *) = optval;
931 error = sooptcopyout(sopt, &optval, sizeof optval);
915 break;
916
917 case IP_MULTICAST_IF:
918 case IP_MULTICAST_VIF:
919 case IP_MULTICAST_TTL:
920 case IP_MULTICAST_LOOP:
921 case IP_ADD_MEMBERSHIP:
922 case IP_DROP_MEMBERSHIP:
932 break;
933
934 case IP_MULTICAST_IF:
935 case IP_MULTICAST_VIF:
936 case IP_MULTICAST_TTL:
937 case IP_MULTICAST_LOOP:
938 case IP_ADD_MEMBERSHIP:
939 case IP_DROP_MEMBERSHIP:
923 error = ip_getmoptions(optname, inp->inp_moptions, mp);
940 error = ip_getmoptions(sopt, inp->inp_moptions);
924 break;
925
941 break;
942
926 case IP_PORTRANGE:
927 *mp = m = m_get(M_WAIT, MT_SOOPTS);
928 m->m_len = sizeof(int);
929
930 if (inp->inp_flags & INP_HIGHPORT)
931 optval = IP_PORTRANGE_HIGH;
932 else if (inp->inp_flags & INP_LOWPORT)
933 optval = IP_PORTRANGE_LOW;
934 else
935 optval = 0;
936
937 *mtod(m, int *) = optval;
938 break;
939
940 default:
941 error = ENOPROTOOPT;
942 break;
943 }
944 break;
945 }
946 return (error);
947}
948
949/*
950 * Set up IP options in pcb for insertion in output packets.
951 * Store in mbuf with pointer in pcbopt, adding pseudo-option
952 * with destination address if source routed.
953 */
954static int
943 default:
944 error = ENOPROTOOPT;
945 break;
946 }
947 break;
948 }
949 return (error);
950}
951
952/*
953 * Set up IP options in pcb for insertion in output packets.
954 * Store in mbuf with pointer in pcbopt, adding pseudo-option
955 * with destination address if source routed.
956 */
957static int
955#ifdef notyet
956ip_pcbopts(optname, pcbopt, m)
957 int optname;
958ip_pcbopts(optname, pcbopt, m)
959 int optname;
958#else
959ip_pcbopts(pcbopt, m)
960#endif
961 struct mbuf **pcbopt;
962 register struct mbuf *m;
963{
964 register int cnt, optlen;
965 register u_char *cp;
966 u_char opt;
967
968 /* turn off any old options */

--- 80 unchanged lines hidden (view full) ---

1049 return (0);
1050
1051bad:
1052 (void)m_free(m);
1053 return (EINVAL);
1054}
1055
1056/*
960 struct mbuf **pcbopt;
961 register struct mbuf *m;
962{
963 register int cnt, optlen;
964 register u_char *cp;
965 u_char opt;
966
967 /* turn off any old options */

--- 80 unchanged lines hidden (view full) ---

1048 return (0);
1049
1050bad:
1051 (void)m_free(m);
1052 return (EINVAL);
1053}
1054
1055/*
1056 * XXX
1057 * The whole multicast option thing needs to be re-thought.
1058 * Several of these options are equally applicable to non-multicast
1059 * transmission, and one (IP_MULTICAST_TTL) totally duplicates a
1060 * standard option (IP_TTL).
1061 */
1062/*
1057 * Set the IP multicast options in response to user setsockopt().
1058 */
1059static int
1063 * Set the IP multicast options in response to user setsockopt().
1064 */
1065static int
1060ip_setmoptions(optname, imop, m)
1061 int optname;
1066ip_setmoptions(sopt, imop)
1067 struct sockopt *sopt;
1062 struct ip_moptions **imop;
1068 struct ip_moptions **imop;
1063 struct mbuf *m;
1064{
1069{
1065 register int error = 0;
1066 u_char loop;
1067 register int i;
1070 int error = 0;
1071 int i;
1068 struct in_addr addr;
1072 struct in_addr addr;
1069 register struct ip_mreq *mreq;
1070 register struct ifnet *ifp;
1071 register struct ip_moptions *imo = *imop;
1073 struct ip_mreq mreq;
1074 struct ifnet *ifp;
1075 struct ip_moptions *imo = *imop;
1072 struct route ro;
1076 struct route ro;
1073 register struct sockaddr_in *dst;
1077 struct sockaddr_in *dst;
1074 int s;
1075
1076 if (imo == NULL) {
1077 /*
1078 * No multicast option buffer attached to the pcb;
1079 * allocate one and initialize to default values.
1080 */
1081 imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,

--- 4 unchanged lines hidden (view full) ---

1086 *imop = imo;
1087 imo->imo_multicast_ifp = NULL;
1088 imo->imo_multicast_vif = -1;
1089 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
1090 imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
1091 imo->imo_num_memberships = 0;
1092 }
1093
1078 int s;
1079
1080 if (imo == NULL) {
1081 /*
1082 * No multicast option buffer attached to the pcb;
1083 * allocate one and initialize to default values.
1084 */
1085 imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,

--- 4 unchanged lines hidden (view full) ---

1090 *imop = imo;
1091 imo->imo_multicast_ifp = NULL;
1092 imo->imo_multicast_vif = -1;
1093 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
1094 imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
1095 imo->imo_num_memberships = 0;
1096 }
1097
1094 switch (optname) {
1098 switch (sopt->sopt_name) {
1095 /* store an index number for the vif you wanna use in the send */
1096 case IP_MULTICAST_VIF:
1099 /* store an index number for the vif you wanna use in the send */
1100 case IP_MULTICAST_VIF:
1097 if (!legal_vif_num) {
1101 if (legal_vif_num == 0) {
1098 error = EOPNOTSUPP;
1099 break;
1100 }
1102 error = EOPNOTSUPP;
1103 break;
1104 }
1101 if (m == NULL || m->m_len != sizeof(int)) {
1102 error = EINVAL;
1105 error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
1106 if (error)
1103 break;
1107 break;
1104 }
1105 i = *(mtod(m, int *));
1106 if (!legal_vif_num(i) && (i != -1)) {
1107 error = EINVAL;
1108 break;
1109 }
1110 imo->imo_multicast_vif = i;
1111 break;
1112
1113 case IP_MULTICAST_IF:
1114 /*
1115 * Select the interface for outgoing multicast packets.
1116 */
1108 if (!legal_vif_num(i) && (i != -1)) {
1109 error = EINVAL;
1110 break;
1111 }
1112 imo->imo_multicast_vif = i;
1113 break;
1114
1115 case IP_MULTICAST_IF:
1116 /*
1117 * Select the interface for outgoing multicast packets.
1118 */
1117 if (m == NULL || m->m_len != sizeof(struct in_addr)) {
1118 error = EINVAL;
1119 error = sooptcopyin(sopt, &addr, sizeof addr, sizeof addr);
1120 if (error)
1119 break;
1121 break;
1120 }
1121 addr = *(mtod(m, struct in_addr *));
1122 /*
1123 * INADDR_ANY is used to remove a previous selection.
1124 * When no interface is selected, a default one is
1125 * chosen every time a multicast packet is sent.
1126 */
1127 if (addr.s_addr == INADDR_ANY) {
1128 imo->imo_multicast_ifp = NULL;
1129 break;

--- 12 unchanged lines hidden (view full) ---

1142 }
1143 imo->imo_multicast_ifp = ifp;
1144 splx(s);
1145 break;
1146
1147 case IP_MULTICAST_TTL:
1148 /*
1149 * Set the IP time-to-live for outgoing multicast packets.
1122 /*
1123 * INADDR_ANY is used to remove a previous selection.
1124 * When no interface is selected, a default one is
1125 * chosen every time a multicast packet is sent.
1126 */
1127 if (addr.s_addr == INADDR_ANY) {
1128 imo->imo_multicast_ifp = NULL;
1129 break;

--- 12 unchanged lines hidden (view full) ---

1142 }
1143 imo->imo_multicast_ifp = ifp;
1144 splx(s);
1145 break;
1146
1147 case IP_MULTICAST_TTL:
1148 /*
1149 * Set the IP time-to-live for outgoing multicast packets.
1150 * The original multicast API required a char argument,
1151 * which is inconsistent with the rest of the socket API.
1152 * We allow either a char or an int.
1150 */
1153 */
1151 if (m == NULL || m->m_len != 1) {
1152 error = EINVAL;
1153 break;
1154 if (sopt->sopt_valsize == 1) {
1155 u_char ttl;
1156 error = sooptcopyin(sopt, &ttl, 1, 1);
1157 if (error)
1158 break;
1159 imo->imo_multicast_ttl = ttl;
1160 } else {
1161 u_int ttl;
1162 error = sooptcopyin(sopt, &ttl, sizeof ttl,
1163 sizeof ttl);
1164 if (error)
1165 break;
1166 if (ttl > 255)
1167 error = EINVAL;
1168 else
1169 imo->imo_multicast_ttl = ttl;
1154 }
1170 }
1155 imo->imo_multicast_ttl = *(mtod(m, u_char *));
1156 break;
1157
1158 case IP_MULTICAST_LOOP:
1159 /*
1160 * Set the loopback flag for outgoing multicast packets.
1171 break;
1172
1173 case IP_MULTICAST_LOOP:
1174 /*
1175 * Set the loopback flag for outgoing multicast packets.
1161 * Must be zero or one.
1176 * Must be zero or one. The original multicast API required a
1177 * char argument, which is inconsistent with the rest
1178 * of the socket API. We allow either a char or an int.
1162 */
1179 */
1163 if (m == NULL || m->m_len != 1 ||
1164 (loop = *(mtod(m, u_char *))) > 1) {
1165 error = EINVAL;
1166 break;
1180 if (sopt->sopt_valsize == 1) {
1181 u_char loop;
1182 error = sooptcopyin(sopt, &loop, 1, 1);
1183 if (error)
1184 break;
1185 imo->imo_multicast_loop = !!loop;
1186 } else {
1187 u_int loop;
1188 error = sooptcopyin(sopt, &loop, sizeof loop,
1189 sizeof loop);
1190 if (error)
1191 break;
1192 imo->imo_multicast_loop = !!loop;
1167 }
1193 }
1168 imo->imo_multicast_loop = loop;
1169 break;
1170
1171 case IP_ADD_MEMBERSHIP:
1172 /*
1173 * Add a multicast group membership.
1174 * Group must be a valid IP multicast address.
1175 */
1194 break;
1195
1196 case IP_ADD_MEMBERSHIP:
1197 /*
1198 * Add a multicast group membership.
1199 * Group must be a valid IP multicast address.
1200 */
1176 if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1177 error = EINVAL;
1201 error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
1202 if (error)
1178 break;
1203 break;
1179 }
1180 mreq = mtod(m, struct ip_mreq *);
1181 if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
1204
1205 if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
1182 error = EINVAL;
1183 break;
1184 }
1185 s = splimp();
1186 /*
1187 * If no interface address was provided, use the interface of
1188 * the route to the given multicast address.
1189 */
1206 error = EINVAL;
1207 break;
1208 }
1209 s = splimp();
1210 /*
1211 * If no interface address was provided, use the interface of
1212 * the route to the given multicast address.
1213 */
1190 if (mreq->imr_interface.s_addr == INADDR_ANY) {
1214 if (mreq.imr_interface.s_addr == INADDR_ANY) {
1191 bzero((caddr_t)&ro, sizeof(ro));
1192 dst = (struct sockaddr_in *)&ro.ro_dst;
1193 dst->sin_len = sizeof(*dst);
1194 dst->sin_family = AF_INET;
1215 bzero((caddr_t)&ro, sizeof(ro));
1216 dst = (struct sockaddr_in *)&ro.ro_dst;
1217 dst->sin_len = sizeof(*dst);
1218 dst->sin_family = AF_INET;
1195 dst->sin_addr = mreq->imr_multiaddr;
1219 dst->sin_addr = mreq.imr_multiaddr;
1196 rtalloc(&ro);
1197 if (ro.ro_rt == NULL) {
1198 error = EADDRNOTAVAIL;
1199 splx(s);
1200 break;
1201 }
1202 ifp = ro.ro_rt->rt_ifp;
1203 rtfree(ro.ro_rt);
1204 }
1205 else {
1220 rtalloc(&ro);
1221 if (ro.ro_rt == NULL) {
1222 error = EADDRNOTAVAIL;
1223 splx(s);
1224 break;
1225 }
1226 ifp = ro.ro_rt->rt_ifp;
1227 rtfree(ro.ro_rt);
1228 }
1229 else {
1206 INADDR_TO_IFP(mreq->imr_interface, ifp);
1230 INADDR_TO_IFP(mreq.imr_interface, ifp);
1207 }
1208
1209 /*
1210 * See if we found an interface, and confirm that it
1211 * supports multicast.
1212 */
1213 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1214 error = EADDRNOTAVAIL;
1215 splx(s);
1216 break;
1217 }
1218 /*
1219 * See if the membership already exists or if all the
1220 * membership slots are full.
1221 */
1222 for (i = 0; i < imo->imo_num_memberships; ++i) {
1223 if (imo->imo_membership[i]->inm_ifp == ifp &&
1224 imo->imo_membership[i]->inm_addr.s_addr
1231 }
1232
1233 /*
1234 * See if we found an interface, and confirm that it
1235 * supports multicast.
1236 */
1237 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1238 error = EADDRNOTAVAIL;
1239 splx(s);
1240 break;
1241 }
1242 /*
1243 * See if the membership already exists or if all the
1244 * membership slots are full.
1245 */
1246 for (i = 0; i < imo->imo_num_memberships; ++i) {
1247 if (imo->imo_membership[i]->inm_ifp == ifp &&
1248 imo->imo_membership[i]->inm_addr.s_addr
1225 == mreq->imr_multiaddr.s_addr)
1249 == mreq.imr_multiaddr.s_addr)
1226 break;
1227 }
1228 if (i < imo->imo_num_memberships) {
1229 error = EADDRINUSE;
1230 splx(s);
1231 break;
1232 }
1233 if (i == IP_MAX_MEMBERSHIPS) {
1234 error = ETOOMANYREFS;
1235 splx(s);
1236 break;
1237 }
1238 /*
1239 * Everything looks good; add a new record to the multicast
1240 * address list for the given interface.
1241 */
1242 if ((imo->imo_membership[i] =
1250 break;
1251 }
1252 if (i < imo->imo_num_memberships) {
1253 error = EADDRINUSE;
1254 splx(s);
1255 break;
1256 }
1257 if (i == IP_MAX_MEMBERSHIPS) {
1258 error = ETOOMANYREFS;
1259 splx(s);
1260 break;
1261 }
1262 /*
1263 * Everything looks good; add a new record to the multicast
1264 * address list for the given interface.
1265 */
1266 if ((imo->imo_membership[i] =
1243 in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
1267 in_addmulti(&mreq.imr_multiaddr, ifp)) == NULL) {
1244 error = ENOBUFS;
1245 splx(s);
1246 break;
1247 }
1248 ++imo->imo_num_memberships;
1249 splx(s);
1250 break;
1251
1252 case IP_DROP_MEMBERSHIP:
1253 /*
1254 * Drop a multicast group membership.
1255 * Group must be a valid IP multicast address.
1256 */
1268 error = ENOBUFS;
1269 splx(s);
1270 break;
1271 }
1272 ++imo->imo_num_memberships;
1273 splx(s);
1274 break;
1275
1276 case IP_DROP_MEMBERSHIP:
1277 /*
1278 * Drop a multicast group membership.
1279 * Group must be a valid IP multicast address.
1280 */
1257 if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1258 error = EINVAL;
1281 error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
1282 if (error)
1259 break;
1283 break;
1260 }
1261 mreq = mtod(m, struct ip_mreq *);
1262 if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
1284
1285 if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
1263 error = EINVAL;
1264 break;
1265 }
1266
1267 s = splimp();
1268 /*
1269 * If an interface address was specified, get a pointer
1270 * to its ifnet structure.
1271 */
1286 error = EINVAL;
1287 break;
1288 }
1289
1290 s = splimp();
1291 /*
1292 * If an interface address was specified, get a pointer
1293 * to its ifnet structure.
1294 */
1272 if (mreq->imr_interface.s_addr == INADDR_ANY)
1295 if (mreq.imr_interface.s_addr == INADDR_ANY)
1273 ifp = NULL;
1274 else {
1296 ifp = NULL;
1297 else {
1275 INADDR_TO_IFP(mreq->imr_interface, ifp);
1298 INADDR_TO_IFP(mreq.imr_interface, ifp);
1276 if (ifp == NULL) {
1277 error = EADDRNOTAVAIL;
1278 splx(s);
1279 break;
1280 }
1281 }
1282 /*
1283 * Find the membership in the membership array.
1284 */
1285 for (i = 0; i < imo->imo_num_memberships; ++i) {
1286 if ((ifp == NULL ||
1287 imo->imo_membership[i]->inm_ifp == ifp) &&
1288 imo->imo_membership[i]->inm_addr.s_addr ==
1299 if (ifp == NULL) {
1300 error = EADDRNOTAVAIL;
1301 splx(s);
1302 break;
1303 }
1304 }
1305 /*
1306 * Find the membership in the membership array.
1307 */
1308 for (i = 0; i < imo->imo_num_memberships; ++i) {
1309 if ((ifp == NULL ||
1310 imo->imo_membership[i]->inm_ifp == ifp) &&
1311 imo->imo_membership[i]->inm_addr.s_addr ==
1289 mreq->imr_multiaddr.s_addr)
1312 mreq.imr_multiaddr.s_addr)
1290 break;
1291 }
1292 if (i == imo->imo_num_memberships) {
1293 error = EADDRNOTAVAIL;
1294 splx(s);
1295 break;
1296 }
1297 /*

--- 29 unchanged lines hidden (view full) ---

1327
1328 return (error);
1329}
1330
1331/*
1332 * Return the IP multicast options in response to user getsockopt().
1333 */
1334static int
1313 break;
1314 }
1315 if (i == imo->imo_num_memberships) {
1316 error = EADDRNOTAVAIL;
1317 splx(s);
1318 break;
1319 }
1320 /*

--- 29 unchanged lines hidden (view full) ---

1350
1351 return (error);
1352}
1353
1354/*
1355 * Return the IP multicast options in response to user getsockopt().
1356 */
1357static int
1335ip_getmoptions(optname, imo, mp)
1336 int optname;
1358ip_getmoptions(sopt, imo)
1359 struct sockopt *sopt;
1337 register struct ip_moptions *imo;
1360 register struct ip_moptions *imo;
1338 register struct mbuf **mp;
1339{
1361{
1340 u_char *ttl;
1341 u_char *loop;
1342 struct in_addr *addr;
1362 struct in_addr addr;
1343 struct in_ifaddr *ia;
1363 struct in_ifaddr *ia;
1364 int error, optval;
1365 u_char coptval;
1344
1366
1345 *mp = m_get(M_WAIT, MT_SOOPTS);
1346
1347 switch (optname) {
1348
1367 error = 0;
1368 switch (sopt->sopt_name) {
1349 case IP_MULTICAST_VIF:
1350 if (imo != NULL)
1369 case IP_MULTICAST_VIF:
1370 if (imo != NULL)
1351 *(mtod(*mp, int *)) = imo->imo_multicast_vif;
1371 optval = imo->imo_multicast_vif;
1352 else
1372 else
1353 *(mtod(*mp, int *)) = -1;
1354 (*mp)->m_len = sizeof(int);
1355 return(0);
1373 optval = -1;
1374 error = sooptcopyout(sopt, &optval, sizeof optval);
1375 break;
1356
1357 case IP_MULTICAST_IF:
1376
1377 case IP_MULTICAST_IF:
1358 addr = mtod(*mp, struct in_addr *);
1359 (*mp)->m_len = sizeof(struct in_addr);
1360 if (imo == NULL || imo->imo_multicast_ifp == NULL)
1378 if (imo == NULL || imo->imo_multicast_ifp == NULL)
1361 addr->s_addr = INADDR_ANY;
1379 addr.s_addr = INADDR_ANY;
1362 else {
1363 IFP_TO_IA(imo->imo_multicast_ifp, ia);
1380 else {
1381 IFP_TO_IA(imo->imo_multicast_ifp, ia);
1364 addr->s_addr = (ia == NULL) ? INADDR_ANY
1365 : IA_SIN(ia)->sin_addr.s_addr;
1382 addr.s_addr = (ia == NULL) ? INADDR_ANY
1383 : IA_SIN(ia)->sin_addr.s_addr;
1366 }
1384 }
1367 return (0);
1385 error = sooptcopyout(sopt, &addr, sizeof addr);
1386 break;
1368
1369 case IP_MULTICAST_TTL:
1387
1388 case IP_MULTICAST_TTL:
1370 ttl = mtod(*mp, u_char *);
1371 (*mp)->m_len = 1;
1372 *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
1373 : imo->imo_multicast_ttl;
1374 return (0);
1389 if (imo == 0)
1390 optval = coptval = IP_DEFAULT_MULTICAST_TTL;
1391 else
1392 optval = coptval = imo->imo_multicast_ttl;
1393 if (sopt->sopt_valsize == 1)
1394 error = sooptcopyout(sopt, &coptval, 1);
1395 else
1396 error = sooptcopyout(sopt, &optval, sizeof optval);
1397 break;
1375
1376 case IP_MULTICAST_LOOP:
1398
1399 case IP_MULTICAST_LOOP:
1377 loop = mtod(*mp, u_char *);
1378 (*mp)->m_len = 1;
1379 *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
1380 : imo->imo_multicast_loop;
1381 return (0);
1400 if (imo == 0)
1401 optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
1402 else
1403 optval = coptval = imo->imo_multicast_loop;
1404 if (sopt->sopt_valsize == 1)
1405 error = sooptcopyout(sopt, &coptval, 1);
1406 else
1407 error = sooptcopyout(sopt, &optval, sizeof optval);
1408 break;
1382
1383 default:
1409
1410 default:
1384 return (EOPNOTSUPP);
1411 error = ENOPROTOOPT;
1412 break;
1385 }
1413 }
1414 return (error);
1386}
1387
1388/*
1389 * Discard the IP multicast options.
1390 */
1391void
1392ip_freemoptions(imo)
1393 register struct ip_moptions *imo;

--- 71 unchanged lines hidden ---
1415}
1416
1417/*
1418 * Discard the IP multicast options.
1419 */
1420void
1421ip_freemoptions(imo)
1422 register struct ip_moptions *imo;

--- 71 unchanged lines hidden ---