1 /* $NetBSD: kern.c,v 1.12 2011/08/31 16:24:59 plunky Exp $ */ 2 3 /* 4 * The mrouted program is covered by the license in the accompanying file 5 * named "LICENSE". Use of the mrouted program represents acceptance of 6 * the terms and conditions listed in that file. 7 * 8 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of 9 * Leland Stanford Junior University. 10 */ 11 12 13 #include "defs.h" 14 15 16 void k_set_rcvbuf(int bufsize) 17 { 18 if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF, 19 (char *)&bufsize, sizeof(bufsize)) < 0) 20 logit(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize); 21 } 22 23 24 void k_hdr_include(int onoff) 25 { 26 #ifdef IP_HDRINCL 27 if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL, 28 (char *)&onoff, sizeof(onoff)) < 0) 29 logit(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", onoff); 30 #endif 31 } 32 33 34 void k_set_ttl(int t) 35 { 36 u_char ttl; 37 38 ttl = t; 39 if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL, 40 (char *)&ttl, sizeof(ttl)) < 0) 41 logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl); 42 } 43 44 45 void k_set_loop(int l) 46 { 47 u_char loop; 48 49 loop = l; 50 if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, 51 (char *)&loop, sizeof(loop)) < 0) 52 logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop); 53 } 54 55 56 void k_set_if(u_int32_t ifa) 57 { 58 struct in_addr adr; 59 60 adr.s_addr = ifa; 61 if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF, 62 (char *)&adr, sizeof(adr)) < 0) 63 logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s", 64 inet_fmt(ifa)); 65 } 66 67 68 void k_join(u_int32_t grp, u_int32_t ifa) 69 { 70 struct ip_mreq mreq; 71 72 mreq.imr_multiaddr.s_addr = grp; 73 mreq.imr_interface.s_addr = ifa; 74 75 if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, 76 (char *)&mreq, sizeof(mreq)) < 0) 77 logit(LOG_WARNING, errno, "can't join group %s on interface %s", 78 inet_fmt(grp), 79 inet_fmt(ifa)); 80 } 81 82 83 void k_leave(u_int32_t grp, u_int32_t ifa) 84 { 85 struct ip_mreq mreq; 86 87 mreq.imr_multiaddr.s_addr = grp; 88 mreq.imr_interface.s_addr = ifa; 89 90 if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, 91 (char *)&mreq, sizeof(mreq)) < 0) 92 logit(LOG_WARNING, errno, "can't leave group %s on interface %s", 93 inet_fmt(grp), 94 inet_fmt(ifa)); 95 } 96 97 98 void k_init_dvmrp(void) 99 { 100 #ifdef OLD_KERNEL 101 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, 102 NULL, 0) < 0) 103 #else 104 int v=1; 105 106 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, 107 (char *)&v, sizeof(int)) < 0) 108 #endif 109 logit(LOG_ERR, errno, "can't enable Multicast routing in kernel"); 110 } 111 112 113 void k_stop_dvmrp(void) 114 { 115 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE, 116 NULL, 0) < 0) 117 logit(LOG_WARNING, errno, "can't disable Multicast routing in kernel"); 118 } 119 120 121 void k_add_vif(vifi_t vifi, struct uvif *v) 122 { 123 struct vifctl vc; 124 125 vc.vifc_vifi = vifi; 126 vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS; 127 vc.vifc_threshold = v->uv_threshold; 128 vc.vifc_rate_limit = v->uv_rate_limit; 129 vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr; 130 vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr; 131 132 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF, 133 (char *)&vc, sizeof(vc)) < 0) 134 logit(LOG_ERR, errno, "setsockopt MRT_ADD_VIF"); 135 } 136 137 138 void k_del_vif(vifi_t vifi) 139 { 140 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF, 141 (char *)&vifi, sizeof(vifi)) < 0) 142 logit(LOG_ERR, errno, "setsockopt MRT_DEL_VIF"); 143 } 144 145 146 /* 147 * Adds a (source, mcastgrp) entry to the kernel 148 */ 149 void k_add_rg(u_int32_t origin, struct gtable *g) 150 { 151 struct mfcctl mc; 152 vifi_t i; 153 154 #ifdef DEBUG_MFC 155 md_log(MD_ADD, origin, g->gt_mcastgrp); 156 #endif 157 /* copy table values so that setsockopt can process it */ 158 mc.mfcc_origin.s_addr = origin; 159 #ifdef OLD_KERNEL 160 mc.mfcc_originmask.s_addr = 0xffffffff; 161 #endif 162 mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; 163 mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF; 164 for (i = 0; i < numvifs; i++) 165 mc.mfcc_ttls[i] = g->gt_ttls[i]; 166 167 /* write to kernel space */ 168 if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC, 169 (char *)&mc, sizeof(mc)) < 0) { 170 #ifdef DEBUG_MFC 171 md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp); 172 #endif 173 logit(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC"); 174 } 175 } 176 177 178 /* 179 * Deletes a (source, mcastgrp) entry from the kernel 180 */ 181 int k_del_rg(u_int32_t origin, struct gtable *g) 182 { 183 struct mfcctl mc; 184 int retval; 185 186 #ifdef DEBUG_MFC 187 md_log(MD_DEL, origin, g->gt_mcastgrp); 188 #endif 189 /* copy table values so that setsockopt can process it */ 190 mc.mfcc_origin.s_addr = origin; 191 #ifdef OLD_KERNEL 192 mc.mfcc_originmask.s_addr = 0xffffffff; 193 #endif 194 mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; 195 196 /* write to kernel space */ 197 if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC, 198 (char *)&mc, sizeof(mc))) < 0) { 199 #ifdef DEBUG_MFC 200 md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp); 201 #endif 202 logit(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC"); 203 } 204 205 return retval; 206 } 207 208 /* 209 * Get the kernel's idea of what version of mrouted needs to run with it. 210 */ 211 int k_get_version(void) 212 { 213 #ifdef OLD_KERNEL 214 return -1; 215 #else 216 int vers; 217 socklen_t len = sizeof(vers); 218 219 if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION, 220 (char *)&vers, &len) < 0) 221 logit(LOG_ERR, errno, 222 "getsockopt MRT_VERSION: perhaps your kernel is too old"); 223 224 return vers; 225 #endif 226 } 227