1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* ----------------------------------------------------------------------------- 25 * 26 * Theory of operation : 27 * 28 * This file implements the ip protocol module for the ppp interface 29 * 30----------------------------------------------------------------------------- */ 31 32/* ----------------------------------------------------------------------------- 33Includes 34----------------------------------------------------------------------------- */ 35 36#include <sys/param.h> 37#include <sys/mbuf.h> 38#include <sys/socket.h> 39#include <sys/syslog.h> 40#include <sys/systm.h> 41#include <sys/malloc.h> 42#include <sys/sockio.h> 43#include <kern/locks.h> 44 45#include <net/if.h> 46#include <net/kpi_protocol.h> 47 48#include <netinet/in.h> 49#include <netinet/in_systm.h> 50#include <netinet/in_var.h> 51#include <netinet/ip.h> 52 53#include "ppp_defs.h" // public ppp values 54#include "ppp_ipv6.h" 55#include "ppp_domain.h" 56#include "ppp_if.h" 57#include "if_ppplink.h" 58 59 60/* ----------------------------------------------------------------------------- 61Definitions 62----------------------------------------------------------------------------- */ 63 64/* ----------------------------------------------------------------------------- 65Forward declarations 66----------------------------------------------------------------------------- */ 67 68static errno_t ppp_ipv6_input(ifnet_t ifp, protocol_family_t protocol, 69 mbuf_t packet, char* header); 70static errno_t ppp_ipv6_preoutput(ifnet_t ifp, protocol_family_t protocol, 71 mbuf_t *packet, const struct sockaddr *dest, 72 void *route, char *frame_type, char *link_layer_dest); 73static errno_t ppp_ipv6_ioctl(ifnet_t ifp, protocol_family_t protocol, 74 u_long command, void* argument); 75 76 77/* ----------------------------------------------------------------------------- 78Globals 79----------------------------------------------------------------------------- */ 80extern lck_mtx_t *ppp_domain_mutex; 81 82/* ----------------------------------------------------------------------------- 83init function 84----------------------------------------------------------------------------- */ 85int ppp_ipv6_init(int init_arg) 86{ 87 return proto_register_plumber(PF_INET6, APPLE_IF_FAM_PPP, ppp_ipv6_attach, ppp_ipv6_detach); 88} 89 90/* ----------------------------------------------------------------------------- 91terminate function 92----------------------------------------------------------------------------- */ 93int ppp_ipv6_dispose(int term_arg) 94{ 95 proto_unregister_plumber(PF_INET6, APPLE_IF_FAM_PPP); 96 return 0; 97} 98 99/* ----------------------------------------------------------------------------- 100attach the PPPx interface ifp to the network protocol IPv6, 101called when the ppp interface is ready for ppp traffic 102----------------------------------------------------------------------------- */ 103errno_t ppp_ipv6_attach(ifnet_t ifp, protocol_family_t protocol) 104{ 105 int ret; 106 struct ifnet_attach_proto_param reg; 107 struct ppp_if *wan = (struct ppp_if *)ifnet_softc(ifp); 108 109 LOGDBG(ifp, ("ppp_ipv6_attach: name = %s, unit = %d\n", ifnet_name(ifp), ifnet_unit(ifp))); 110 111 if (wan->ipv6_attached) 112 return 0; // already attached 113 114 bzero(®, sizeof(struct ifnet_attach_proto_param)); 115 116 reg.input = ppp_ipv6_input; 117 reg.pre_output = ppp_ipv6_preoutput; 118 reg.ioctl = ppp_ipv6_ioctl; 119 ret = ifnet_attach_protocol(ifp, PF_INET6, ®); 120 LOGRETURN(ret, ret, "ppp_ipv6_attach: ifnet_attach_protocol error = 0x%x\n"); 121 122 LOGDBG(ifp, ("ppp_ipv6_attach: ifnet_attach_protocol family = 0x%x\n", protocol)); 123 wan->ipv6_attached = 1; 124 125 return 0; 126} 127 128/* ----------------------------------------------------------------------------- 129detach the PPPx interface ifp from the network protocol IPv6, 130called when the ppp interface stops ip traffic 131----------------------------------------------------------------------------- */ 132void ppp_ipv6_detach(ifnet_t ifp, protocol_family_t protocol) 133{ 134 int ret; 135 struct ppp_if *wan = (struct ppp_if *)ifnet_softc(ifp); 136 137 LOGDBG(ifp, ("ppp_ipv6_detach\n")); 138 139 if (!wan->ipv6_attached) 140 return; // already detached 141 142 ret = ifnet_detach_protocol(ifp, PF_INET6); 143 if (ret) 144 IOLog("ppp_ipv6_detach: ifnet_detach_protocol error = 0x%x\n", ret); 145 146 wan->ipv6_attached = 0; 147} 148 149/* ----------------------------------------------------------------------------- 150called from dlil when an ioctl is sent to the interface 151----------------------------------------------------------------------------- */ 152errno_t ppp_ipv6_ioctl(ifnet_t ifp, protocol_family_t protocol, 153 u_long command, void* argument) 154{ 155 struct sockaddr_in6 addr6; 156 int error = 0; 157 158 switch (command) { 159 160 case SIOCSIFADDR: 161 case SIOCAIFADDR: 162 LOGDBG(ifp, ("ppp_ipv6_ioctl: cmd = SIOCSIFADDR/SIOCAIFADDR\n")); 163 164 error = ifaddr_address(argument, (struct sockaddr *)&addr6, sizeof (addr6)); 165 if (error != 0) { 166 error = EAFNOSUPPORT; 167 break; 168 } 169 170 // only an IPv6 address should arrive here 171 if (addr6.sin6_family != AF_INET6) { 172 error = EAFNOSUPPORT; 173 break; 174 } 175 break; 176 177 default : 178 error = EOPNOTSUPP; 179 } 180 181 return error; 182} 183 184/* ----------------------------------------------------------------------------- 185called from dlil when a packet from the interface is to be dispatched to 186the specific network protocol attached by dl_tag. 187the network protocol has been determined earlier by the demux function. 188the packet is in the mbuf chain m without 189the frame header, which is provided separately. (not used) 190----------------------------------------------------------------------------- */ 191errno_t ppp_ipv6_input(ifnet_t ifp, protocol_family_t protocol, 192 mbuf_t packet, char* header) 193{ 194 LOGMBUF("ppp_ipv6_input", packet); 195 196 if (proto_input(PF_INET6, packet)) 197 mbuf_freem(packet); 198 199 return 0; 200} 201 202/* ----------------------------------------------------------------------------- 203pre_output function 204----------------------------------------------------------------------------- */ 205errno_t ppp_ipv6_preoutput(ifnet_t ifp, protocol_family_t protocol, 206 mbuf_t *packet, const struct sockaddr *dest, 207 void *route, char *frame_type, char *link_layer_dest) 208{ 209 u_int16_t ftype = PPP_IPV6; 210 211 LOGMBUF("ppp_ipv6_preoutput", *packet); 212 213 memcpy(frame_type, &ftype, sizeof(u_int16_t)); 214 return 0; 215} 216 217