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