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 interface driver for the ppp family 29* 30* it's the responsability of the driver to update the statistics 31* whenever that makes sense 32* ifnet.if_lastchange = a packet is present, a packet starts to be sent 33* ifnet.if_ibytes = nb of correct PPP bytes received (does not include escapes...) 34* ifnet.if_obytes = nb of correct PPP bytes sent (does not include escapes...) 35* ifnet.if_ipackets = nb of PPP packet received 36* ifnet.if_opackets = nb of PPP packet sent 37* ifnet.if_ierrors = nb on input packets in error 38* ifnet.if_oerrors = nb on ouptut packets in error 39* 40----------------------------------------------------------------------------- */ 41 42 43/* ----------------------------------------------------------------------------- 44Includes 45----------------------------------------------------------------------------- */ 46 47#include <sys/param.h> 48#include <sys/systm.h> 49#include <sys/kpi_mbuf.h> 50#include <sys/socket.h> 51#include <sys/malloc.h> 52#include <sys/syslog.h> 53#include <sys/sockio.h> 54#include <sys/kernel.h> 55#include <kern/clock.h> 56 57#include <net/if_types.h> 58#include <netinet/in.h> 59#include <netinet/tcp.h> 60#include <netinet/in_systm.h> 61#include <net/bpf.h> 62#include <net/kpi_interface.h> 63#include <net/if.h> 64 65#include "slcompress.h" 66#include "ppp_defs.h" // public ppp values 67#include "if_ppp.h" // public ppp API 68#include "if_ppplink.h" // public link API 69#include "ppp_domain.h" 70#include "ppp_if.h" 71#include "ppp_ip.h" 72#include "ppp_ipv6.h" 73#include "ppp_compress.h" 74#include "ppp_comp.h" 75#include "ppp_link.h" 76 77 78/* ----------------------------------------------------------------------------- 79Definitions 80----------------------------------------------------------------------------- */ 81 82/* ----------------------------------------------------------------------------- 83Forward declarations 84----------------------------------------------------------------------------- */ 85 86static void ppp_if_start(ifnet_t interface); 87static errno_t ppp_if_output(ifnet_t ifp, mbuf_t m); 88static void ppp_if_if_free(ifnet_t ifp); 89static errno_t ppp_if_ioctl(ifnet_t ifp, u_long cmd, void *data); 90static int ppp_if_demux(ifnet_t ifp, mbuf_t m, char *frame_header, 91 protocol_family_t *protocol_family); 92static int ppp_if_add_proto(ifnet_t ifp, protocol_family_t protocol_family, 93 const struct ifnet_demux_desc *demux_list, u_int32_t demux_count); 94static int ppp_if_del_proto(ifnet_t ifp, protocol_family_t protocol_family); 95#if KPI_INTERFACE_EMBEDDED 96static errno_t ppp_if_frameout(ifnet_t ifp, mbuf_t *m0, 97 const struct sockaddr *ndest, const char *edst, const char *ppp_type, 98 u_int32_t *pre, u_int32_t *post); 99#else /* KPI_INTERFACE_EMBEDDED */ 100static errno_t ppp_if_frameout(ifnet_t ifp, mbuf_t *m0, 101 const struct sockaddr *ndest, const char *edst, const char *ppp_type); 102#endif /* !KPI_INTERFACE_EMBEDDED */ 103 104static int ppp_if_detach(ifnet_t ifp); 105static struct ppp_if *ppp_if_findunit(u_short unit); 106static int ppp_if_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, bpf_packet_func func); 107 108/* ----------------------------------------------------------------------------- 109Globals 110----------------------------------------------------------------------------- */ 111 112static TAILQ_HEAD(, ppp_if) ppp_if_head; 113static lck_grp_attr_t *ppp_if_lck_grp_attr = 0; 114static lck_attr_t *ppp_if_lck_attr = 0; 115static lck_grp_t *ppp_if_lck_grp = 0; 116 117extern lck_mtx_t *ppp_domain_mutex; 118 119/* ----------------------------------------------------------------------------- 120----------------------------------------------------------------------------- */ 121int ppp_if_init() 122{ 123 TAILQ_INIT(&ppp_if_head); 124 125 ppp_if_lck_grp_attr = lck_grp_attr_alloc_init(); 126 LOGNULLFAIL(ppp_if_lck_grp_attr, "ppp_if_init: lck_grp_attr_alloc_init failed\n"); 127 128 lck_grp_attr_setdefault(ppp_if_lck_grp_attr); 129 130 ppp_if_lck_grp = lck_grp_alloc_init("PPP", ppp_if_lck_grp_attr); 131 LOGNULLFAIL(ppp_if_lck_grp, "ppp_if_init: lck_grp_alloc_init failed\n"); 132 133 ppp_if_lck_attr = lck_attr_alloc_init(); 134 LOGNULLFAIL(ppp_if_lck_attr, "ppp_if_init: lck_attr_alloc_init failed\n"); 135 136 lck_attr_setdefault(ppp_if_lck_attr); 137 //lck_attr_setdebug(ppp_if_lck_attr); 138 139 return 0; 140 141fail: 142 if (ppp_if_lck_grp) { 143 lck_grp_free(ppp_if_lck_grp); 144 ppp_if_lck_grp = 0; 145 } 146 if (ppp_if_lck_grp_attr) { 147 lck_grp_attr_free(ppp_if_lck_grp_attr); 148 ppp_if_lck_grp_attr = 0; 149 } 150 if (ppp_if_lck_attr) { 151 lck_attr_free(ppp_if_lck_attr); 152 ppp_if_lck_attr = 0; 153 } 154 return KERN_FAILURE; 155 156} 157 158/* ----------------------------------------------------------------------------- 159----------------------------------------------------------------------------- */ 160int ppp_if_dispose() 161{ 162 163 // can't dispose if interface are in use 164 if (!TAILQ_EMPTY(&ppp_if_head)) 165 return EBUSY; 166 167 lck_grp_free(ppp_if_lck_grp); 168 ppp_if_lck_grp = 0; 169 170 lck_grp_attr_free(ppp_if_lck_grp_attr); 171 ppp_if_lck_grp_attr = 0; 172 173 lck_attr_free(ppp_if_lck_attr); 174 ppp_if_lck_attr = 0; 175 176 return 0; 177} 178 179/* ----------------------------------------------------------------------------- 180----------------------------------------------------------------------------- */ 181int ppp_if_attach(u_short *unit) 182{ 183 int ret = 0; 184 struct ppp_if *wan, *wan1; 185 struct ifnet_init_eparams init; 186 struct ifnet_stats_param stats; 187 188 MALLOC(wan, struct ppp_if *, sizeof(struct ppp_if), M_TEMP, M_WAITOK); 189 if (!wan) 190 return ENOMEM; 191 192 bzero(wan, sizeof(struct ppp_if)); 193 wan->unit = 0xFFFF; 194 195 wan1 = TAILQ_FIRST(&ppp_if_head); 196 197 if (*unit != 0xFFFF) { 198 // if a specific nuber has been requested, find if not in use, and insert it 199 while (wan1) { 200 if (wan1->unit == *unit) { 201 // in use, just return error. 202 lck_mtx_unlock(ppp_domain_mutex); 203 ret = EINVAL; 204 goto error_nolock; 205 } 206 if (wan1->unit > *unit) 207 break; 208 wan1 = TAILQ_NEXT(wan1, next); 209 } 210 } 211 else { 212 // find a free unit and insert it, keep the list ordered 213 *unit = 0; 214 wan1 = TAILQ_FIRST(&ppp_if_head); 215 while (wan1) { 216 if (wan1->unit > *unit) 217 break; 218 *unit = wan1->unit + 1; 219 wan1 = TAILQ_NEXT(wan1, next); 220 } 221 } 222 223 wan->mtx = lck_mtx_alloc_init(ppp_if_lck_grp, ppp_if_lck_attr); 224 if (wan->mtx == 0) { 225 lck_mtx_unlock(ppp_domain_mutex); 226 ret = ENOMEM; 227 goto error_nolock; 228 } 229 230 wan->unit = *unit; 231 if (wan1) 232 TAILQ_INSERT_BEFORE(wan1, wan, next); 233 else 234 TAILQ_INSERT_TAIL(&ppp_if_head, wan, next); 235 236 bzero(&init, sizeof(init)); 237 init.ver = IFNET_INIT_CURRENT_VERSION; 238 init.len = sizeof(init); 239 init.name = APPLE_PPP_NAME; 240 init.unit = *unit; 241 init.family = IFNET_FAMILY_PPP; 242 init.type = IFT_PPP; 243 init.start = ppp_if_start; 244 init.demux = ppp_if_demux; 245 init.add_proto = ppp_if_add_proto; 246 init.del_proto = ppp_if_del_proto; 247 init.framer = ppp_if_frameout; 248 init.softc = wan; 249 init.ioctl = ppp_if_ioctl; 250 init.detach = ppp_if_if_free; 251 init.set_bpf_tap = ppp_if_set_bpf_tap; 252 253 lck_mtx_unlock(ppp_domain_mutex); 254 255 ret = ifnet_allocate_extended(&init, &wan->net); 256 if (ret) 257 goto error_nolock; 258 259 TAILQ_INIT(&wan->link_head); 260 261 ifnet_set_hdrlen(wan->net, PPP_HDRLEN); 262 ifnet_set_flags(wan->net, IFF_POINTOPOINT | IFF_MULTICAST, 0xFFFF); // || IFF_RUNNING 263 ifnet_set_mtu(wan->net, PPP_MTU); 264 ifnet_set_baudrate(wan->net, 0 /* 10 Mbits/s ??? */); 265 bzero(&stats, sizeof(stats)); 266 ifnet_set_stat(wan->net, &stats); 267 /* 268 * A PPP interface does generate its own IPv6 LinkLocal address 269 */ 270 ifnet_set_eflags(wan->net, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL); 271 ifnet_touch_lastchange(wan->net); 272 273 ret = ifnet_attach(wan->net, NULL); 274 if (ret) 275 goto error_nolock; 276 277 bpfattach(wan->net, DLT_PPP, PPP_HDRLEN); 278 279 // attach network protocols 280 281 wan->sndq.maxlen = IFQ_MAXLEN; 282 wan->npmode[NP_IP] = NPMODE_ERROR; 283 wan->npmode[NP_IPV6] = NPMODE_ERROR; 284 285 lck_mtx_lock(ppp_domain_mutex); 286 return 0; 287 288error_nolock: 289 if (wan->net) 290 ifnet_release(wan->net); 291 if (wan->mtx) 292 lck_mtx_free(wan->mtx, ppp_if_lck_grp); 293 lck_mtx_lock(ppp_domain_mutex); 294 if (wan->unit != 0xFFFF) { 295 TAILQ_REMOVE(&ppp_if_head, wan, next); 296 } 297 FREE(wan, M_TEMP); 298 return ret; 299} 300 301/* ----------------------------------------------------------------------------- 302detach ppp interface from dlil layer 303----------------------------------------------------------------------------- */ 304int ppp_if_detach(ifnet_t ifp) 305{ 306 struct ppp_if *wan = ifnet_softc(ifp); 307 int ret; 308 struct ppp_link *link; 309 mbuf_t m; 310 311 // need to remove all ref to ifnet in link structures 312 TAILQ_FOREACH(link, &wan->link_head, lk_bdl_next) { 313 // do we need a free function ? 314 link->lk_ifnet = 0; 315 } 316 317 ppp_comp_close(wan); 318 319 // detach protocols when detaching interface, just in case pppd forgot... 320 321 lck_mtx_unlock(ppp_domain_mutex); 322 ppp_ipv6_detach(ifp, PF_INET6); 323 ppp_ip_detach(ifp, PF_INET); 324 lck_mtx_lock(ppp_domain_mutex); 325 326 if (wan->vjcomp) { 327 FREE(wan->vjcomp, M_TEMP); 328 wan->vjcomp = 0; 329 } 330 331 wan->state |= PPP_IF_STATE_DETACHING; 332 lck_mtx_unlock(ppp_domain_mutex); 333 ret = ifnet_detach(ifp); 334 if (ret) { 335 wan->state &= ~PPP_IF_STATE_DETACHING; 336 lck_mtx_lock(ppp_domain_mutex); 337 return KERN_FAILURE; 338 } 339 340 lck_mtx_lock(wan->mtx); 341 /* interface release is in progress, wait for callback */ 342 if (wan->state & PPP_IF_STATE_DETACHING) 343 msleep(ifp, wan->mtx, PZERO+1, 0, 0); 344 lck_mtx_unlock(wan->mtx); 345 346 //sleep(ifp, PZERO+1); 347 lck_mtx_lock(ppp_domain_mutex); 348 349 do { 350 m = ppp_dequeue(&wan->sndq); 351 mbuf_freem(m); 352 } while (m); 353 354 lck_mtx_unlock(ppp_domain_mutex); 355 ifnet_release(ifp); 356 lck_mtx_lock(ppp_domain_mutex); 357 TAILQ_REMOVE(&ppp_if_head, wan, next); 358 lck_mtx_free(wan->mtx, ppp_if_lck_grp); 359 FREE(wan, M_TEMP); 360 361 return 0; 362} 363 364/* ----------------------------------------------------------------------------- 365----------------------------------------------------------------------------- */ 366int ppp_if_attachclient(u_short unit, void *host, ifnet_t *ifp) 367{ 368 struct ppp_if *wan; 369 370 wan = ppp_if_findunit(unit); 371 if (!wan) 372 return ENODEV; 373 374 *ifp = wan->net; 375 if (!wan->host) // don't override the first attachment (use a list ?) 376 wan->host = host; 377 wan->nbclients++; 378 379 return 0; 380} 381 382/* ----------------------------------------------------------------------------- 383----------------------------------------------------------------------------- */ 384void ppp_if_detachclient(ifnet_t ifp, void *host) 385{ 386 struct ppp_if *wan = ifnet_softc(ifp); 387 388 if (wan->host) { 389 if (wan->host == host) 390 wan->host = 0; 391 wan->nbclients--; 392 if (!wan->nbclients) 393 ppp_if_detach(ifp); 394 } 395} 396 397/* ----------------------------------------------------------------------------- 398find a the unit number in the interface list 399----------------------------------------------------------------------------- */ 400struct ppp_if *ppp_if_findunit(u_short unit) 401{ 402 struct ppp_if *wan; 403 404 TAILQ_FOREACH(wan, &ppp_if_head, next) { 405 if (wan->unit == unit) 406 return wan; 407 } 408 return NULL; 409} 410 411/* ----------------------------------------------------------------------------- 412----------------------------------------------------------------------------- */ 413static errno_t 414ppp_if_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, 415 bpf_packet_func func) 416{ 417 struct ppp_if *wan = ifnet_softc(ifp); 418 419 lck_mtx_lock(ppp_domain_mutex); 420 421 switch (mode) { 422 case BPF_MODE_DISABLED: 423 wan->bpf_input = wan->bpf_output = NULL; 424 break; 425 426 case BPF_MODE_INPUT: 427 wan->bpf_input = func; 428 break; 429 430 case BPF_MODE_OUTPUT: 431 wan->bpf_output = func; 432 break; 433 434 case BPF_MODE_INPUT_OUTPUT: 435 wan->bpf_input = wan->bpf_output = func; 436 break; 437 default: 438 break; 439 } 440 lck_mtx_unlock(ppp_domain_mutex); 441 return 0; 442} 443 444/* ----------------------------------------------------------------------------- 445mbuf debugging 446----------------------------------------------------------------------------- */ 447 448#ifdef LOGDATA 449 450static void 451snprintf_mbuf(char *s, size_t len, mbuf_t m, const char *prefix, const char *suffix) 452{ 453 if (m) { 454 if ((mbuf_flags(m) & MBUF_PKTHDR)) 455 snprintf(s, len, 456 "%s%p type %u len %u data %p maxlen %u datastart %p next %p flags %x pktlen %u nextpkt %p header %p%s", 457 prefix ? prefix : "", 458 m, mbuf_type(m), mbuf_len(m), mbuf_data(m), mbuf_maxlen(m), mbuf_datastart(m), mbuf_next(m), 459 mbuf_flags(m), mbuf_pkthdr_len(m), mbuf_nextpkt(m), mbuf_pkthdr_header(m), 460 suffix ? suffix : ""); 461 else 462 snprintf(s, len, 463 "%s%p type %u len %u data %p maxlen %u datastart %p next %p flags %x%s", 464 prefix ? prefix : "", 465 m, mbuf_type(m), mbuf_len(m), mbuf_data(m), mbuf_maxlen(m), mbuf_datastart(m), mbuf_next(m), 466 mbuf_flags(m), 467 suffix ? suffix : ""); 468 } else 469 snprintf(s, len, "%s<NULL>%s", prefix, suffix); 470} 471 472static void 473DumpHex(char *line, size_t maxline, unsigned char *buffer, size_t len) 474{ 475 size_t i; 476 int n = 0; 477 478 for (i = 0; i < len; i += 16) { 479 size_t j; 480 481 if (n > maxline) return; 482 n += snprintf(line + n, maxline - n, "%06d: ", i); 483 for (j = i; j < len && j < i + 16; j++) { 484 if (n > maxline) return; 485 n += snprintf(line + n, maxline - n, "%02x ", buffer[j]); 486 } 487 for (; j < i + 16; j++) { 488 if (n > maxline) return; 489 n += snprintf(line + n, maxline - n, " "); 490 } 491 for (j = i; j < len && j < i + 16; j++) { 492 int c = buffer[j]; 493 494 if (c < 0x20 || c > 0x7E) 495 c = '.'; 496 if (n > maxline) return; 497 n += snprintf(line + n, maxline - n, "%c", c); 498 } 499 n += snprintf(line + n, maxline - n, "\n"); 500 } 501} 502 503static void 504log_mbuf(ifnet_t ifp, mbuf_t m, const char *msg) 505{ 506 char mbuf_str[160]; 507 char data_str[160]; 508 509 snprintf_mbuf(mbuf_str, sizeof(mbuf_str), m, NULL, NULL); 510 DumpHex(data_str, sizeof(data_str), mbuf_data(m), MIN(mbuf_len(m), 32)); 511 LOGDBG(ifp, ("ppp%d: %s: %s\n", ifnet_unit(ifp), msg, mbuf_str)); 512 LOGDBG(ifp, ("%s\n", data_str)); 513} 514 515#endif /* LOGDATA */ 516 517/* ----------------------------------------------------------------------------- 518called when data are present 519----------------------------------------------------------------------------- */ 520int ppp_if_input(ifnet_t ifp, mbuf_t m, u_int16_t proto, u_int16_t hdrlen) 521{ 522 struct ppp_if *wan = ifnet_softc(ifp); 523 int inlen, vjlen; 524 u_char *iphdr, *p = mbuf_data(m); // no alignment issue as p is *u_char. 525 u_int hlen; 526 int error = ENOMEM; 527 struct timespec tv; 528 struct ifnet_stat_increment_param statsinc; 529 u_int16_t aligned_short; 530 531 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 532 533 mbuf_pkthdr_setheader(m, p); // header point to the protocol header (0x21 or 0x0021) 534 mbuf_adj(m, hdrlen); // the packet points to the real data (0x45) 535 p = mbuf_data(m); 536 537 if (wan->sc_flags & SC_DECOMP_RUN) { 538 switch (proto) { 539 case PPP_COMP: 540 if (ppp_comp_decompress(wan, &m) != DECOMP_OK) { 541 LOGDBG(ifp, ("ppp%d: decompression error\n", ifnet_unit(ifp))); 542 goto free; 543 } 544 p = mbuf_data(m); 545 proto = p[0]; 546 hdrlen = 1; 547 if (!(proto & 0x1)) { // lowest bit set for lowest byte of protocol 548 proto = (proto << 8) + p[1]; 549 hdrlen = 2; 550 } 551 mbuf_pkthdr_setheader(m, p);// header point to the protocol header (0x21 or 0x0021) 552 mbuf_adj(m, hdrlen); // the packet points to the real data (0x45) 553 p = mbuf_data(m); 554 break; 555 default: 556 ppp_comp_incompress(wan, m); 557 } 558 } 559 560 switch (proto) { 561 case PPP_VJC_COMP: 562 case PPP_VJC_UNCOMP: 563 if (!(wan->sc_flags & SC_COMP_TCP)) 564 goto reject; 565 566 if (!wan->vjcomp) { 567 LOGDBG(ifp, ("ppp%d: VJ structure not allocated\n", ifnet_unit(ifp))); 568 goto free; 569 } 570 571 inlen = mbuf_pkthdr_len(m); 572 573 /* 574 * We should make sure the header is contiguous in the mbuf of the compress/decompress routines 575 * Do not ask more than the mbuf contains 576 */ 577 if (mbuf_len(m) < MIN(inlen, sizeof(struct ip) + sizeof(struct tcphdr))) { 578 mbuf_t new_m = NULL; 579 size_t offset = 0; 580 size_t len = MIN(inlen, sizeof(struct ip) + sizeof(struct tcphdr)); 581 582#ifdef LOGDATA 583 log_mbuf(ifp, m, proto == PPP_VJC_COMP ? "PPP_VJC_COMP" : "PPP_VJC_UNCOMP"); 584#endif 585 if (mbuf_pulldown(m, &offset, len, &new_m) != 0) { 586 LOGDBG(ifp, ("ppp%d: mbuf_pulldown failed\n", ifnet_unit(ifp))); 587 goto end; 588 } 589 if (new_m != m) { 590 m = new_m; 591#ifdef LOGDATA 592 log_mbuf(ifp, m, "pulled-down"); 593#endif 594 } 595 } 596 if (proto == PPP_VJC_COMP) { 597 598 vjlen = sl_uncompress_tcp_core(p, mbuf_len(m), inlen, TYPE_COMPRESSED_TCP, 599 wan->vjcomp, &iphdr, &hlen); 600 601 if (vjlen <= 0) { 602 LOGDBG(ifp, ("ppp%d: VJ uncompress failed on type PPP_VJC_COMP\n", ifnet_unit(ifp))); 603 goto free; 604 } 605 606 // we must move data in the buffer, to add the uncompressed TCP/IP header... 607 if (mbuf_trailingspace(m) < (hlen - vjlen)) { 608 LOGDBG(ifp, ("ppp%d: VJ uncompress failed: trailingspace (%d) < hlen (%d) - vjlen (%d)\n", ifnet_unit(ifp), 609 mbuf_trailingspace(m), hlen, vjlen)); 610 goto free; 611 } 612 bcopy(p + vjlen, p + hlen, inlen - vjlen); 613 bcopy(iphdr, p, hlen); 614 mbuf_setlen(m, mbuf_len(m) + hlen - vjlen); 615 mbuf_pkthdr_setlen(m, mbuf_pkthdr_len(m) + hlen - vjlen); 616 } 617 else { 618 vjlen = sl_uncompress_tcp_core(p, mbuf_len(m), inlen, TYPE_UNCOMPRESSED_TCP, 619 wan->vjcomp, &iphdr, &hlen); 620 621 if (vjlen < 0) { 622 LOGDBG(ifp, ("ppp%d: VJ uncompress failed on type TYPE_UNCOMPRESSED_TCP\n", ifnet_unit(ifp))); 623 goto free; 624 } 625 } 626 *(u_char *)mbuf_pkthdr_header(m) = PPP_IP; // change the protocol, use 1 byte 627 proto = PPP_IP; 628 //no break; 629 case PPP_IP: 630 if (wan->npmode[NP_IP] != NPMODE_PASS) 631 goto reject; 632 if (wan->npafmode[NP_IP] & NPAFMODE_SRC_IN) { 633 if (ppp_ip_af_src_in(ifp, mbuf_data(m))) { 634 error = 0; 635 goto free; 636 } 637 } 638 if (wan->npafmode[NP_IP] & NPAFMODE_DHCP_INTERCEPT_SERVER) { 639 if (ppp_ip_bootp_server_in(ifp, mbuf_data(m))) 640 goto reject; 641 } 642 if (wan->npafmode[NP_IP] & NPAFMODE_DHCP_INTERCEPT_CLIENT) { 643 if (ppp_ip_bootp_client_in(ifp, mbuf_data(m))) 644 goto reject; 645 } 646 break; 647 case PPP_IPV6: 648 if (wan->npmode[NP_IPV6] != NPMODE_PASS) 649 goto reject; 650 break; 651 case PPP_CCP: 652 ppp_comp_ccp(wan, m, 1); 653 goto reject; 654 default: 655 goto reject; 656 } 657 658 // See if bpf wants to look at the packet. 659 if (wan->bpf_input) { 660 if (mbuf_prepend(&m, 4, MBUF_WAITOK) != 0) { 661 bzero(&statsinc, sizeof(statsinc)); 662 statsinc.errors_in = 1; 663 ifnet_stat_increment(ifp, &statsinc); 664 return ENOMEM; 665 } 666 p = mbuf_data(m); 667 // Wcast-align fix for unaligned move 668 aligned_short = htons(0xFF03); 669 *p++ = *((u_int8_t *)&aligned_short); 670 *p++ = *(((u_int8_t *)&aligned_short) + 1); 671 aligned_short = htons(proto); 672 *p++ = *((u_int8_t *)&aligned_short); 673 *p++ = *(((u_int8_t *)&aligned_short) + 1); 674 (*wan->bpf_input)(ifp, m); 675 mbuf_adj(m, 4); 676 } 677 678 bzero(&statsinc, sizeof(statsinc)); 679 statsinc.packets_in = 1; 680 statsinc.bytes_in = mbuf_pkthdr_len(m); 681 mbuf_pkthdr_setrcvif(m, ifp); 682 nanouptime(&tv); 683 wan->last_recv = tv.tv_sec; 684 685 lck_mtx_unlock(ppp_domain_mutex); 686 ifnet_input(ifp, m, &statsinc); 687 lck_mtx_lock(ppp_domain_mutex); 688 return 0; 689 690reject: 691 692 // unexpected network protocol, prepend the 2 bytes protocol header expected by pppd 693 if (mbuf_prepend(&m, 2, MBUF_WAITOK) != 0) { 694 bzero(&statsinc, sizeof(statsinc)); 695 statsinc.errors_in = 1; 696 ifnet_stat_increment(ifp, &statsinc); 697 return ENOMEM; 698 } 699 p = mbuf_data(m); 700 // Wcast-align fix for unaligned move 701 aligned_short = htons(proto); 702 *p++ = *((u_int8_t *)&aligned_short); 703 *p++ = *(((u_int8_t *)&aligned_short) + 1); 704 ppp_proto_input(wan->host, m); 705 return 0; 706 707free: 708 mbuf_freem(m); 709end: 710 bzero(&statsinc, sizeof(statsinc)); 711 statsinc.errors_in = 1; 712 ifnet_stat_increment(ifp, &statsinc); 713 return error; 714} 715 716/* ----------------------------------------------------------------------------- 717This gets called when the interface is freed 718(if dlil_if_detach has returned DLIL_WAIT_FOR_FREE) 719----------------------------------------------------------------------------- */ 720void ppp_if_if_free(ifnet_t ifp) 721{ 722 struct ppp_if *wan = ifnet_softc(ifp); 723 724 lck_mtx_lock(wan->mtx); 725 wan->state &= ~PPP_IF_STATE_DETACHING; 726 lck_mtx_unlock(wan->mtx); 727 wakeup(ifp); 728} 729 730/* ----------------------------------------------------------------------------- 731Process an ioctl request to the ppp interface 732----------------------------------------------------------------------------- */ 733int ppp_if_control(ifnet_t ifp, u_long cmd, void *data) 734{ 735 struct ppp_if *wan = ifnet_softc(ifp); 736 int error = 0, npx; 737 u_int16_t mru, flags16; 738 u_int32_t flags; 739 u_int32_t t; 740 struct npioctl *npi; 741 struct npafioctl *npafi; 742 struct timespec tv; 743 struct ifpppdelegate *ifdelegate; 744 ifnet_t del_ifp = NULL; 745 746 //LOGDBG(ifp, ("ppp_if_control, (ifnet = %s%d), cmd = 0x%x\n", ifp->if_name, ifp->if_unit, cmd)); 747 748 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 749 750 switch (cmd) { 751 case PPPIOCSDEBUG: 752 flags = *(int *)data; 753 LOGDBG(ifp, ("ppp_if_control: PPPIOCSDEBUG (level = 0x%x)\n", flags)); 754 flags16 = 0; 755 if (flags & 1) flags16 |= IFF_DEBUG; // general purpose debugging 756 if (flags & 2) flags16 |= PPP_LOG_INPKT; // trace all packets in 757 if (flags & 4) flags16 |= PPP_LOG_OUTPKT; // trace all packets out 758 ifnet_set_flags(ifp, flags16, IFF_DEBUG + PPP_LOG_INPKT + PPP_LOG_OUTPKT); 759 break; 760 761 case PPPIOCGDEBUG: 762 flags16 = ifnet_flags(ifp); 763 flags = 0; 764 if (flags16 & IFF_DEBUG) flags |= 1; 765 if (flags16 & PPP_LOG_INPKT) flags |= 2; 766 if (flags16 & PPP_LOG_OUTPKT) flags |= 4; 767 *(int *)data = flags; 768 LOGDBG(ifp, ("ppp_if_control: PPPIOCGDEBUG (level = 0x%x)\n", flags)); 769 break; 770 771 case PPPIOCSMRU: 772 LOGDBG(ifp, ("ppp_if_control: PPPIOCSMRU\n")); 773 mru = *(int *)data; 774 wan->mru = mru; 775 break; 776 777 case PPPIOCSFLAGS: 778 flags = *(int *)data & SC_MASK; 779 LOGDBG(ifp, ("ppp_if_control: PPPIOCSFLAGS, old flags = 0x%x new flags = 0x%x, \n", wan->sc_flags, (wan->sc_flags & ~SC_MASK) | flags)); 780 wan->sc_flags = (wan->sc_flags & ~SC_MASK) | flags; 781 break; 782 783 case PPPIOCGFLAGS: 784 LOGDBG(ifp, ("ppp_if_control: PPPIOCGFLAGS\n")); 785 *(int *)data = wan->sc_flags; 786 break; 787 788 case PPPIOCSCOMPRESS32: 789 case PPPIOCSCOMPRESS64: 790 error = ppp_comp_setcompressor(wan, data); 791 break; 792 793 case PPPIOCGUNIT: 794 LOGDBG(ifp, ("ppp_if_control: PPPIOCGUNIT\n")); 795 *(int *)data = ifnet_unit(ifp); 796 break; 797 798 case PPPIOCGIDLE: 799 LOGDBG(ifp, ("ppp_if_control: PPPIOCGIDLE\n")); 800 nanouptime(&tv); 801 t = tv.tv_sec; 802 ((struct ppp_idle *)data)->xmit_idle = t - wan->last_xmit; 803 ((struct ppp_idle *)data)->recv_idle = t - wan->last_recv; 804 break; 805 806 case PPPIOCSMAXCID: 807 LOGDBG(ifp, ("ppp_if_control: PPPIOCSMAXCID\n")); 808 // allocate the vj structure first 809 if (!wan->vjcomp) { 810 MALLOC(wan->vjcomp, struct slcompress *, sizeof(struct slcompress), 811 M_TEMP, M_WAITOK); 812 if (!wan->vjcomp) 813 return ENOMEM; 814 sl_compress_init(wan->vjcomp, -1); 815 } 816 // reeinit the compressor 817 sl_compress_init(wan->vjcomp, *(int *)data); 818 break; 819 820 case PPPIOCSNPMODE: 821 case PPPIOCGNPMODE: 822 LOGDBG(ifp, ("ppp_if_control: PPPIOCSNPMODE/PPPIOCGNPMODE\n")); 823 npi = (struct npioctl *) data; 824 switch (npi->protocol) { 825 case PPP_IP: 826 npx = NP_IP; 827 break; 828 case PPP_IPV6: 829 npx = NP_IPV6; 830 break; 831 default: 832 return EINVAL; 833 } 834 if (cmd == PPPIOCGNPMODE) { 835 npi->mode = wan->npmode[npx]; 836 } else { 837 if (npi->mode != wan->npmode[npx]) { 838 wan->npmode[npx] = npi->mode; 839 if (npi->mode != NPMODE_QUEUE) { 840 //ppp_requeue(sc); 841 //(*sc->sc_start)(sc); 842 } 843 } 844 } 845 break; 846 847 case PPPIOCSNPAFMODE: 848 case PPPIOCGNPAFMODE: 849 LOGDBG(ifp, ("ppp_if_control: PPPIOCSNPAFMODE/PPPIOCGNPAFMODE\n")); 850 npafi = (struct npafioctl *) data; 851 switch (npafi->protocol) { 852 case PPP_IP: 853 npx = NP_IP; 854 break; 855 case PPP_IPV6: 856 npx = NP_IPV6; 857 break; 858 default: 859 return EINVAL; 860 } 861 if (cmd == PPPIOCGNPMODE) { 862 npafi->mode = wan->npafmode[npx]; 863 } else { 864 wan->npafmode[npx] = npafi->mode; 865 } 866 break; 867 868 case PPPIOCSDELEGATE: 869 LOGDBG(ifp, ("ppp_if_control: PPPIOCSDELEGATE\n")); 870 ifdelegate = (struct ifpppdelegate*)data; 871 if (strlen(ifdelegate->ifr_delegate_name) != 0) 872 error = ifnet_find_by_name(ifdelegate->ifr_delegate_name, &del_ifp); 873 if (error == 0) { 874 error = ifnet_set_delegate(ifp, del_ifp); 875 if (del_ifp) 876 ifnet_release(del_ifp); 877 } 878 break; 879 880 default: 881 LOGDBG(ifp, ("ppp_if_control: unknown ioctl\n")); 882 error = EINVAL; 883 } 884 885 return error; 886} 887 888/* ----------------------------------------------------------------------------- 889Process an ioctl request to the ppp interface 890----------------------------------------------------------------------------- */ 891errno_t ppp_if_ioctl(ifnet_t ifp, u_long cmd, void *data) 892{ 893 //struct ppp_if *wan = ifp->if_softc; 894 struct ifreq *ifr = (struct ifreq *)data; 895 int error = 0; 896 struct ppp_stats *psp; 897 struct ifnet_stats_param statspar; 898 899 //LOGDBG(ifp, ("ppp_if_ioctl, cmd = 0x%x\n", cmd)); 900 901 lck_mtx_lock(ppp_domain_mutex); 902 903 switch (cmd) { 904 905 case SIOCSIFFLAGS: 906 LOGDBG(ifp, ("ppp_if_ioctl: cmd = SIOCSIFFLAGS\n")); 907 // even if this case does nothing, it must be there to return 0 908 //if ((ifp->if_flags & IFF_RUNNING) == 0) 909 // ifp->if_flags &= ~IFF_UP; 910 break; 911 912 case SIOCSIFADDR: 913 case SIOCAIFADDR: 914 LOGDBG(ifp, ("ppp_if_ioctl: cmd = SIOCSIFADDR/SIOCAIFADDR\n")); 915 // dlil protocol module already took care of the ioctl 916 break; 917 918 case SIOCADDMULTI: 919 case SIOCDELMULTI: 920 LOGDBG(ifp, ("ppp_if_ioctl: cmd = SIOCADDMULTI/SIOCDELMULTI\n")); 921 break; 922 923 case SIOCDIFADDR: 924 LOGDBG(ifp, ("ppp_if_ioctl: cmd = SIOCDIFADDR\n")); 925 break; 926 927 case SIOCSIFDSTADDR: 928 LOGDBG(ifp, ("ppp_if_ioctl: cmd = SIOCSIFDSTADDR\n")); 929 break; 930 931 case SIOCGPPPSTATS: 932 LOGDBG(ifp, ("ppp_if_ioctl, SIOCGPPPSTATS\n")); 933 psp = &((struct ifpppstatsreq *) data)->stats; 934 bzero(psp, sizeof(*psp)); 935 ifnet_stat(ifp, &statspar); 936 /* 937 XXX ppp pcounters are only 32 bits. 938 need to implement a second ioctl 939 for 64 bits conters 940 */ 941 psp->p.ppp_ibytes = statspar.bytes_in; 942 psp->p.ppp_obytes = statspar.bytes_out; 943 psp->p.ppp_ipackets = statspar.packets_in; 944 psp->p.ppp_opackets = statspar.packets_out; 945 psp->p.ppp_ierrors = statspar.errors_in; 946 psp->p.ppp_oerrors = statspar.errors_out; 947 948#if 0 949 if (sc->sc_comp) { 950 psp->vj.vjs_packets = sc->sc_comp->sls_packets; 951 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed; 952 psp->vj.vjs_searches = sc->sc_comp->sls_searches; 953 psp->vj.vjs_misses = sc->sc_comp->sls_misses; 954 psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin; 955 psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin; 956 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin; 957 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed; 958 } 959#endif 960 break; 961 962 case SIOCSIFMTU: 963 LOGDBG(ifp, ("ppp_if_ioctl, SIOCSIFMTU\n")); 964 // should we check the minimum MTU for all channels attached to that interface ? 965 if (ifr->ifr_mtu > PPP_MTU) 966 error = EINVAL; 967 else 968 ifnet_set_mtu(ifp, ifr->ifr_mtu); 969 break; 970 971 default: 972 LOGDBG(ifp, ("ppp_if_ioctl, unknown ioctl, cmd = 0x%x\n", cmd)); 973 error = EOPNOTSUPP; 974 } 975 lck_mtx_unlock(ppp_domain_mutex); 976 return error; 977} 978 979/* ----------------------------------------------------------------------------- 980This gets called at splnet from if_ppp.c at various times 981when there is data ready to be sent 982----------------------------------------------------------------------------- */ 983static void ppp_if_start(ifnet_t interface) 984{ 985 mbuf_t data; 986 987 for (;;) { 988 if (ifnet_dequeue(interface, &data) != 0) 989 break; 990 if (ppp_if_output(interface, data) != 0) 991 break; 992 } 993} 994 995errno_t ppp_if_output(ifnet_t ifp, mbuf_t m) 996{ 997 struct ppp_if *wan = ifnet_softc(ifp); 998 int error = 0; 999 u_int16_t proto; 1000 enum NPmode mode; 1001 enum NPAFmode afmode; 1002 char *p; 1003 struct timespec tv; 1004 struct ifnet_stat_increment_param statsinc; 1005 1006 lck_mtx_lock(ppp_domain_mutex); 1007 1008 // clear any flag that can confuse the underlying driver 1009 mbuf_setflags(m, mbuf_flags(m) & ~(MBUF_BCAST + MBUF_MCAST)); 1010 1011 memcpy(&proto, mbuf_data(m), sizeof(u_int16_t)); 1012 proto = ntohs(proto); 1013 1014 switch (proto) { 1015 case PPP_IP: 1016 mode = wan->npmode[NP_IP]; 1017 afmode = wan->npafmode[NP_IP]; 1018 break; 1019 case PPP_IPV6: 1020 mode = wan->npmode[NP_IPV6]; 1021 afmode = wan->npafmode[NP_IPV6]; 1022 break; 1023 default: 1024 // should never happen, since we attached the protocol ourself 1025 error = EAFNOSUPPORT; 1026 goto bad; 1027 } 1028 1029 switch (mode) { 1030 case NPMODE_ERROR: 1031 error = ENETDOWN; 1032 goto bad; 1033 case NPMODE_QUEUE: 1034 case NPMODE_DROP: 1035 error = 0; 1036 goto bad; 1037 case NPMODE_PASS: 1038 break; 1039 } 1040 1041 if (afmode & NPAFMODE_SRC_OUT) { 1042 if (mbuf_len(m) < (sizeof(struct ip) + 2) && 1043 mbuf_pullup(&m, sizeof(struct ip) + 2)) { 1044 if (m) { 1045 mbuf_free(m); 1046 m = NULL; 1047 } 1048 bzero(&statsinc, sizeof(statsinc)); 1049 statsinc.errors_out = 1; 1050 ifnet_stat_increment(ifp, &statsinc); 1051 lck_mtx_unlock(ppp_domain_mutex); 1052 return ENOBUFS; 1053 } 1054 p = mbuf_data(m); 1055 p += 2; 1056 switch (proto) { 1057 case PPP_IP: 1058 error = ppp_ip_af_src_out(ifp, p); 1059 break; 1060 } 1061 if (error) { 1062 error = 0; 1063 goto bad; 1064 } 1065 } 1066 1067 // See if bpf wants to look at the packet. 1068 lck_mtx_unlock(ppp_domain_mutex); 1069 if (wan->bpf_output) { 1070 if (mbuf_prepend(&m, 2, MBUF_WAITOK) != 0) { 1071 bzero(&statsinc, sizeof(statsinc)); 1072 statsinc.errors_out = 1; 1073 ifnet_stat_increment(ifp, &statsinc); 1074 return ENOBUFS; 1075 } 1076 proto = htons(0xFF03); 1077 memcpy(mbuf_data(m), &proto, sizeof(u_int16_t)); 1078 (*wan->bpf_output)(ifp, m); 1079 mbuf_adj(m, 2); 1080 } 1081 lck_mtx_lock(ppp_domain_mutex); 1082 1083 // Update interface statistics. 1084 ifnet_touch_lastchange(ifp); 1085 nanouptime(&tv); 1086 wan->last_xmit = tv.tv_sec; 1087 bzero(&statsinc, sizeof(statsinc)); 1088 statsinc.bytes_out = mbuf_pkthdr_len(m) - 2; // don't count protocol header; 1089 statsinc.packets_out = 1; 1090 ifnet_stat_increment(ifp, &statsinc); 1091 1092 if (wan->sc_flags & SC_LOOP_TRAFFIC) { 1093 ppp_proto_input(wan->host, m); 1094 lck_mtx_unlock(ppp_domain_mutex); 1095 return 0; 1096 } 1097 1098 error = ppp_if_send(ifp, m); 1099 lck_mtx_unlock(ppp_domain_mutex); 1100 return error; 1101 1102bad: 1103 mbuf_freem(m); 1104 bzero(&statsinc, sizeof(statsinc)); 1105 statsinc.errors_out = 1; 1106 ifnet_stat_increment(ifp, &statsinc); 1107 lck_mtx_unlock(ppp_domain_mutex); 1108 return error; 1109} 1110 1111/* ----------------------------------------------------------------------------- 1112add protocol function 1113called from dlil when a network protocol is attached for an 1114interface from that family (i.e ip is attached through ppp_attach_ip) 1115----------------------------------------------------------------------------- */ 1116int ppp_if_add_proto(ifnet_t ifp, protocol_family_t protocol_family, 1117 const struct ifnet_demux_desc *demux_list, u_int32_t demux_count) 1118{ 1119 LOGDBG(ifp, ("ppp_if_add_proto = %d, ifp = %p\n", protocol_family, ifp)); 1120 1121 switch (protocol_family) { 1122 case PF_INET: 1123 case PF_INET6: 1124 break; 1125 default: 1126 return EINVAL; // happen for unknown protocol, or for empty descriptor 1127 } 1128 1129 return 0; 1130} 1131 1132/* ----------------------------------------------------------------------------- 1133delete protocol function 1134called from dlil when a network protocol is detached for an 1135interface from that family (i.e ip is attached through ppp_detach_ip) 1136----------------------------------------------------------------------------- */ 1137int ppp_if_del_proto(ifnet_t ifp, protocol_family_t protocol_family) 1138{ 1139 1140 LOGDBG(ifp, ("ppp_if_del_proto, ifp = %p\n", ifp)); 1141 1142 return 0; 1143} 1144 1145/* ----------------------------------------------------------------------------- 1146demux function 1147----------------------------------------------------------------------------- */ 1148int ppp_if_demux(ifnet_t ifp, mbuf_t m, char *frame_header, 1149 protocol_family_t *protocol_family) 1150{ 1151 u_int16_t proto; 1152 1153 proto = frame_header[0]; 1154 if (!proto & 0x1) { // lowest bit set for lowest byte of protocol 1155 proto = (proto << 8) + frame_header[1]; 1156 } 1157 1158 switch (proto) { 1159 case PPP_IP: 1160 // We could check pppfam->ip_attached, but dlil will handle case where it isn't 1161 *protocol_family = PF_INET; 1162 break; 1163 case PPP_IPV6: 1164 // We could check pppfam->ipv6_attached, but dlil will handle case where it isn't 1165 *protocol_family = PF_INET6; 1166 break; 1167 default : 1168 LOGDBG(ifp, ("ppp_fam_demux, ifp = %p, bad proto = 0x%x\n", ifp, proto)); 1169 return ENOENT; // should never happen 1170 } 1171 1172 return 0; 1173} 1174 1175/* ----------------------------------------------------------------------------- 1176a network packet needs to be send through the interface. 1177add the ppp header to the packet (as a network interface, we only worry 1178about adding our protocol number) 1179----------------------------------------------------------------------------- */ 1180errno_t ppp_if_frameout(ifnet_t ifp, mbuf_t *m0, 1181 const struct sockaddr *ndest, const char *edst, const char *ppp_type 1182#if KPI_INTERFACE_EMBEDDED 1183 , u_int32_t *pre, u_int32_t *post 1184#endif /* KPI_INTERFACE_EMBEDDED */ 1185 ) 1186 1187{ 1188 u_int16_t aligned_type; 1189 1190 struct ifnet_stat_increment_param statsinc; 1191 1192 if (mbuf_prepend(m0, 2, MBUF_DONTWAIT) != 0) { 1193 LOGDBG(ifp, ("ppp_fam_ifoutput : no memory for transmit header\n")); 1194 bzero(&statsinc, sizeof(statsinc)); 1195 statsinc.errors_out = 1; 1196 ifnet_stat_increment(ifp, &statsinc); 1197 return EJUSTRETURN; // just return, because the buffer was freed in m_prepend 1198 } 1199 1200#if KPI_INTERFACE_EMBEDDED 1201 *pre = 2; 1202 *post = 0; 1203#endif /* KPI_INTERFACE_EMBEDDED */ 1204 1205 // place protocol number at the beginning of the mbuf 1206 // Wcast-align fix - memcpy for unaligned moves 1207 memcpy(&aligned_type, ppp_type, sizeof(aligned_type)); 1208 aligned_type = htons(aligned_type); 1209 memcpy(mbuf_data(*m0), &aligned_type, sizeof(aligned_type)); 1210 1211 1212 return 0; 1213} 1214 1215/* ----------------------------------------------------------------------------- 1216 * Connect a PPP channel to a PPP interface unit. 1217----------------------------------------------------------------------------- */ 1218int ppp_if_attachlink(struct ppp_link *link, int unit) 1219{ 1220 struct ppp_if *wan; 1221 1222 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 1223 1224 if (link->lk_ifnet) // already attached 1225 return EINVAL; 1226 1227 wan = ppp_if_findunit(unit); 1228 if (!wan) 1229 return EINVAL; 1230 1231 ifnet_set_flags(wan->net, IFF_RUNNING, IFF_RUNNING); 1232 ifnet_set_baudrate(wan->net, ifnet_baudrate(wan->net) + link->lk_baudrate); 1233 1234 TAILQ_INSERT_TAIL(&wan->link_head, link, lk_bdl_next); 1235 wan->nblinks++; 1236 link->lk_ifnet = wan->net; 1237 1238 return 0; 1239} 1240 1241/* ----------------------------------------------------------------------------- 1242 * Disconnect a channel from its ppp unit. 1243----------------------------------------------------------------------------- */ 1244int ppp_if_detachlink(struct ppp_link *link) 1245{ 1246 ifnet_t ifp = (__typeof__(ifp))link->lk_ifnet; 1247 struct ppp_if *wan; 1248 1249 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 1250 1251 if (!ifp) 1252 return EINVAL; // link already detached 1253 1254 wan = ifnet_softc(ifp); 1255 1256 // check if this is the last link, when multilink is coded 1257 ifnet_set_flags(ifp, 0, IFF_RUNNING); 1258 ifnet_set_baudrate(ifp, ifnet_baudrate(ifp) - link->lk_baudrate); 1259 1260 TAILQ_REMOVE(&wan->link_head, link, lk_bdl_next); 1261 wan->nblinks--; 1262 link->lk_ifnet = 0; 1263 return 0; 1264} 1265 1266/* ----------------------------------------------------------------------------- 1267----------------------------------------------------------------------------- */ 1268int ppp_if_send(ifnet_t ifp, mbuf_t m) 1269{ 1270 struct ppp_if *wan = ifnet_softc(ifp); 1271 u_int16_t proto; 1272 struct ifnet_stat_increment_param statsinc; 1273 int error = 0; 1274 1275 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 1276 1277 memcpy(&proto, mbuf_data(m), sizeof(u_int16_t)); // always the 2 first bytes 1278 proto = ntohs(proto); 1279 1280 if (ppp_qfull(&wan->sndq)) { 1281 ppp_drop(&wan->sndq); 1282 bzero(&statsinc, sizeof(statsinc)); 1283 statsinc.errors_out = 1; 1284 ifnet_stat_increment(ifp, &statsinc); 1285 mbuf_freem(m); 1286 return ENOBUFS; 1287 } 1288 1289 switch (proto) { 1290 case PPP_IP: 1291 // see if we can compress it 1292 if ((wan->sc_flags & SC_COMP_TCP) && wan->vjcomp) { 1293 mbuf_t mp = m; 1294 struct ip ip_data, *ip = mbuf_data(m) + 2; 1295 int vjtype, len; 1296 1297 // skip mbuf, in case the ppp header and ip header are not in the same mbuf 1298 if (mbuf_len(mp) <= 2) { 1299 mp = mbuf_next(mp); 1300 if (!mp) 1301 break; 1302 ip = mbuf_data(mp); 1303 } 1304 1305 memcpy(&ip_data, ip, sizeof(ip_data)); 1306 1307 // this code assumes the IP/TCP header is in one non-shared mbuf 1308 if (ip_data.ip_p == IPPROTO_TCP) { 1309 vjtype = sl_compress_tcp(mp, &ip_data, wan->vjcomp, !(wan->sc_flags & SC_NO_TCP_CCID)); 1310 memcpy(ip, &ip_data, sizeof(ip_data)); 1311 switch (vjtype) { 1312 case TYPE_UNCOMPRESSED_TCP: 1313 proto = htons(PPP_VJC_UNCOMP); // update protocol 1314 break; 1315 case TYPE_COMPRESSED_TCP: 1316 proto = htons(PPP_VJC_COMP); // header has moved, update protocol 1317 memcpy(mbuf_data(m), &proto, sizeof(u_int16_t)); 1318 break; 1319 } 1320 // adjust packet len 1321 len = 0; 1322 for (mp = m; mp != 0; mp = mbuf_next(mp)) 1323 len += mbuf_len(mp); 1324 mbuf_pkthdr_setlen(m, len); 1325 } 1326 } 1327 break; 1328 case PPP_CCP: 1329 mbuf_adj(m, 2); 1330 ppp_comp_ccp(wan, m, 0); 1331 if (mbuf_prepend(&m, 2, MBUF_DONTWAIT) != 0) { 1332 bzero(&statsinc, sizeof(statsinc)); 1333 statsinc.errors_out = 1; 1334 ifnet_stat_increment(ifp, &statsinc); 1335 return ENOBUFS; 1336 } 1337 break; 1338 } 1339 1340 if (wan->sc_flags & SC_COMP_RUN) { 1341 1342 if (ppp_comp_compress(wan, &m) == COMP_OK) { 1343 if (mbuf_prepend(&m, 2, MBUF_DONTWAIT) != 0) { 1344 bzero(&statsinc, sizeof(statsinc)); 1345 statsinc.errors_out = 1; 1346 ifnet_stat_increment(ifp, &statsinc); 1347 return ENOBUFS; 1348 } 1349 proto = htons(PPP_COMP); // update protocol 1350 memcpy(mbuf_data(m), &proto, sizeof(u_int16_t)); 1351 } 1352 } 1353 1354 if (wan->sndq.len) { 1355 ppp_enqueue(&wan->sndq, m); 1356 } 1357 else 1358 error = ppp_if_xmit(ifp, m); 1359 1360 return error; 1361} 1362 1363/* ----------------------------------------------------------------------------- 1364----------------------------------------------------------------------------- */ 1365int ppp_if_xmit(ifnet_t ifp, mbuf_t m) 1366{ 1367 struct ppp_if *wan = ifnet_softc(ifp); 1368 struct ppp_link *link; 1369 int error = 0, len; 1370 struct ifnet_stat_increment_param statsinc; 1371 1372 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 1373 1374 if (m == 0) 1375 m = ppp_dequeue(&wan->sndq); 1376 1377 while (m) { 1378 1379 link = TAILQ_FIRST(&wan->link_head); 1380 if (link == 0) { 1381 LOGDBG(ifp, ("ppp%d: Trying to send data with link detached\n", ifnet_unit(ifp))); 1382 // just flush everything 1383 error = ENXIO; 1384 goto flush; 1385 } 1386 1387 if (link->lk_flags & SC_HOLD) { 1388 // should try next link 1389 mbuf_freem(m); 1390 m = ppp_dequeue(&wan->sndq); 1391 continue; 1392 } 1393 1394 if (link->lk_flags & (SC_XMIT_BUSY | SC_XMIT_FULL)) { 1395 // should try next link 1396 ppp_prepend(&wan->sndq, m); 1397 return 0; 1398 } 1399 1400 // get the len before we send the packet, 1401 // we can not assume the state of the mbuf when we return 1402 len = mbuf_len(m); 1403 1404 // since we tested the lk_flags, ppp_link_send should not failed 1405 // except if there is a dramatic error 1406 link->lk_flags |= SC_XMIT_BUSY; 1407 error = ppp_link_send(link, m); 1408 link->lk_flags &= ~SC_XMIT_BUSY; 1409 if (error) { 1410 // packet has been freed by link lower layer 1411 m = 0; 1412 goto flush; 1413 } 1414 1415 m = ppp_dequeue(&wan->sndq); 1416 } 1417 1418 return 0; 1419 1420flush: 1421 1422 ifnet_touch_lastchange(ifp); 1423 do { 1424 bzero(&statsinc, sizeof(statsinc)); 1425 statsinc.errors_out = 1; 1426 ifnet_stat_increment(ifp, &statsinc); 1427 if (m) 1428 mbuf_freem(m); 1429 m = ppp_dequeue(&wan->sndq); 1430 } 1431 while (m); 1432 return error; 1433} 1434 1435/* ----------------------------------------------------------------------------- 1436----------------------------------------------------------------------------- */ 1437void ppp_if_error(ifnet_t ifp) 1438{ 1439 struct ppp_if *wan = ifnet_softc(ifp); 1440 1441 lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); 1442 1443 // reset vj compression 1444 if (wan->vjcomp) { 1445 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, wan->vjcomp); 1446 } 1447} 1448