1/* $NetBSD: kern.c,v 1.11 2011/02/23 01:23:03 dyoung 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 16void 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 24void 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 34void 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 45void 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 56void 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 68void 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 83void 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 98void 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 113void 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 121void 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 138void 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 */ 149void 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 */ 181int 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 */ 211int 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