nections when roaming. +.El +.Sh EXAMPLES +Display the settings for umb0: +.Bd -literal +# umbctl umb0 +umb0: state up, mode automatic, registration home network + provider "BSD-Net", dataclass LTE, signal good + phone number "+15554242", roaming "" (denied) + APN "", TX 50000000, RX 100000000 + firmware "MBIM_FW_V1.0", hardware "MBIM_HW_V1.0" +.Ed +.Pp +Configure the connection parameters for umb0 from the command line: +.Bd -literal +# umbctl umb0 apn operator.internet username mobile password mobile +.Ed +.Pp +Configure the connection parameters for umb0 from a file: +.Bd -literal +# umbctl -f /dev/stdin umb0 << EOF +pin=1234 +EOF +.Ed +.Sh SEE ALSO +.Xr netstat 1 , +.Xr umb 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +utility first appeared in +.Nx 9.0 , +and +.Fx 15.0 . +.Sh AUTHORS +The program was written by +.An Pierre Pronchery . diff --git a/sbin/umbctl/umbctl.c b/sbin/umbctl/umbctl.c new file mode 100644 index 000000000000..3d57b486ad80 --- /dev/null +++ b/sbin/umbctl/umbctl.c @@ -0,0 +1,557 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Original copyright (c) 2018 Pierre Pronchery (for the + * NetBSD Project) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) 2022 ADISTA SAS (FreeBSD updates) + * + * Updates for FreeBSD by Pierre Pronchery + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: umbctl.c,v 1.4 2020/05/13 21:44:30 khorben Exp $ + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbim.h" +#include "if_umbreg.h" + +/* constants */ +static const struct umb_valdescr _umb_actstate[] = + MBIM_ACTIVATION_STATE_DESCRIPTIONS; + +static const struct umb_valdescr _umb_simstate[] = + MBIM_SIMSTATE_DESCRIPTIONS; + +static const struct umb_valdescr _umb_regstate[] = + MBIM_REGSTATE_DESCRIPTIONS; + +static const struct umb_valdescr _umb_pktstate[] = + MBIM_PKTSRV_STATE_DESCRIPTIONS; + +static const struct umb_valdescr _umb_dataclass[] = + MBIM_DATACLASS_DESCRIPTIONS; + +static const struct umb_valdescr _umb_state[] = + UMB_INTERNAL_STATE_DESCRIPTIONS; + +static const struct umb_valdescr _umb_pin_state[] = +{ + { UMB_PIN_REQUIRED, "PIN required"}, + { UMB_PIN_UNLOCKED, "PIN unlocked"}, + { UMB_PUK_REQUIRED, "PUK required"}, + { 0, NULL } +}; + +static const struct umb_valdescr _umb_regmode[] = +{ + { MBIM_REGMODE_UNKNOWN, "unknown" }, + { MBIM_REGMODE_AUTOMATIC, "automatic" }, + { MBIM_REGMODE_MANUAL, "manual" }, + { 0, NULL } +}; + +static const struct umb_valdescr _umb_ber[] = +{ + { UMB_BER_EXCELLENT, "excellent" }, + { UMB_BER_VERYGOOD, "very good" }, + { UMB_BER_GOOD, "good" }, + { UMB_BER_OK, "ok" }, + { UMB_BER_MEDIUM, "medium" }, + { UMB_BER_BAD, "bad" }, + { UMB_BER_VERYBAD, "very bad" }, + { UMB_BER_EXTREMELYBAD, "extremely bad" }, + { 0, NULL } +}; + + +/* prototypes */ +static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen); +static int _error(int ret, char const * format, ...); +static int _umbctl(char const * ifname, int verbose, int argc, char * argv[]); +static int _umbctl_file(char const * ifname, char const * filename, + int verbose); +static void _umbctl_info(char const * ifname, struct umb_info * umbi); +static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request, + struct ifreq * ifr); +static int _umbctl_set(char const * ifname, struct umb_parameter * umbp, + int argc, char * argv[]); +static int _umbctl_socket(void); +static int _usage(void); +static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen); + + +/* functions */ +/* char_to_utf16 */ +/* this function is from OpenBSD's ifconfig(8) */ +static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen) +{ + int n = 0; + uint16_t c; + + for (;;) { + c = *in++; + + if (c == '\0') { + /* + * NUL termination is not required, but zero out the + * residual buffer + */ + memset(out, 0, outlen); + return n; + } + if (outlen < sizeof(*out)) + return -1; + + *out++ = htole16(c); + n += sizeof(*out); + outlen -= sizeof(*out); + } +} + + +/* error */ +static int _error(int ret, char const * format, ...) +{ + va_list ap; + + fputs("umbctl: ", stderr); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputs("\n", stderr); + return ret; +} + + +/* umbctl */ +static int _umbctl(char const * ifname, int verbose, int argc, char * argv[]) +{ + int fd; + struct ifreq ifr; + struct umb_info umbi; + struct umb_parameter umbp; + + if((fd = _umbctl_socket()) < 0) + return 2; + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if(argc != 0) + { + memset(&umbp, 0, sizeof(umbp)); + ifr.ifr_data = (caddr_t)&umbp; + if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0 + || _umbctl_set(ifname, &umbp, argc, argv) != 0 + || _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM, + &ifr) != 0) + { + close(fd); + return 2; + } + } + if(argc == 0 || verbose > 0) + { + ifr.ifr_data = (caddr_t)&umbi; + if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0) + { + close(fd); + return 3; + } + _umbctl_info(ifname, &umbi); + } + if(close(fd) != 0) + return _error(2, "%s: %s", ifname, strerror(errno)); + return 0; +} + + +/* umbctl_file */ +static int _file_parse(char const * ifname, struct umb_parameter * umbp, + char const * filename); + +static int _umbctl_file(char const * ifname, char const * filename, int verbose) +{ + int fd; + struct ifreq ifr; + struct umb_parameter umbp; + struct umb_info umbi; + + if((fd = _umbctl_socket()) < 0) + return 2; + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&umbp; + memset(&umbp, 0, sizeof(umbp)); + if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0 + || _file_parse(ifname, &umbp, filename) != 0 + || _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM, &ifr) != 0) + { + close(fd); + return 2; + } + if(verbose > 0) + { + ifr.ifr_data = (caddr_t)&umbi; + if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0) + { + close(fd); + return 3; + } + _umbctl_info(ifname, &umbi); + } + if(close(fd) != 0) + return _error(2, "%s: %s", ifname, strerror(errno)); + return 0; +} + +static int _file_parse(char const * ifname, struct umb_parameter * umbp, + char const * filename) +{ + int ret = 0; + FILE * fp; + char buf[512]; + size_t len; + int i; + int eof; + char * tokens[3] = { buf, NULL, NULL }; + char * p; + + if((fp = fopen(filename, "r")) == NULL) + return _error(2, "%s: %s", filename, strerror(errno)); + while(fgets(buf, sizeof(buf), fp) != NULL) + { + if(buf[0] == '#') + continue; + buf[sizeof(buf) - 1] = '\0'; + if((len = strlen(buf)) > 0) + { + if(buf[len - 1] != '\n') + { + ret = _error(2, "%s: %s", filename, + "Line too long"); + while((i = fgetc(fp)) != EOF && i != '\n'); + continue; + } + buf[len - 1] = '\0'; + } + if((p = strchr(buf, '=')) != NULL) + { + tokens[1] = p + 1; + *p = '\0'; + } else + tokens[1] = NULL; + ret |= _umbctl_set(ifname, umbp, (p != NULL) ? 2 : 1, tokens) + ? 2 : 0; + } + eof = feof(fp); + if(fclose(fp) != 0 || !eof) + return _error(2, "%s: %s", filename, strerror(errno)); + return ret; +} + + +/* umbctl_info */ +static void _umbctl_info(char const * ifname, struct umb_info * umbi) +{ + char provider[UMB_PROVIDERNAME_MAXLEN + 1]; + char pn[UMB_PHONENR_MAXLEN + 1]; + char roaming[UMB_ROAMINGTEXT_MAXLEN + 1]; + char apn[UMB_APN_MAXLEN + 1]; + char fwinfo[UMB_FWINFO_MAXLEN + 1]; + char hwinfo[UMB_HWINFO_MAXLEN + 1]; + + _utf16_to_char(umbi->provider, UMB_PROVIDERNAME_MAXLEN, + provider, sizeof(provider)); + _utf16_to_char(umbi->pn, UMB_PHONENR_MAXLEN, pn, sizeof(pn)); + _utf16_to_char(umbi->roamingtxt, UMB_ROAMINGTEXT_MAXLEN, + roaming, sizeof(roaming)); + _utf16_to_char(umbi->apn, UMB_APN_MAXLEN, apn, sizeof(apn)); + _utf16_to_char(umbi->fwinfo, UMB_FWINFO_MAXLEN, fwinfo, sizeof(fwinfo)); + _utf16_to_char(umbi->hwinfo, UMB_HWINFO_MAXLEN, hwinfo, sizeof(hwinfo)); + printf("%s: state %s, mode %s, registration %s\n" + "\tprovider \"%s\", dataclass %s, signal %s\n" + "\tphone number \"%s\", roaming \"%s\" (%s)\n" + "\tAPN \"%s\", TX %" PRIu64 ", RX %" PRIu64 "\n" + "\tfirmware \"%s\", hardware \"%s\"\n", + ifname, umb_val2descr(_umb_state, umbi->state), + umb_val2descr(_umb_regmode, umbi->regmode), + umb_val2descr(_umb_regstate, umbi->regstate), provider, + umb_val2descr(_umb_dataclass, umbi->cellclass), + umb_val2descr(_umb_ber, umbi->ber), pn, roaming, + umbi->enable_roaming ? "allowed" : "denied", + apn, umbi->uplink_speed, umbi->downlink_speed, + fwinfo, hwinfo); +} + + +/* umbctl_ioctl */ +static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request, + struct ifreq * ifr) +{ + if(ioctl(fd, request, ifr) != 0) + return _error(-1, "%s: %s", ifname, strerror(errno)); + return 0; +} + + +/* umbctl_set */ +/* callbacks */ +static int _set_apn(char const *, struct umb_parameter *, char const *); +static int _set_username(char const *, struct umb_parameter *, char const *); +static int _set_password(char const *, struct umb_parameter *, char const *); +static int _set_pin(char const *, struct umb_parameter *, char const *); +static int _set_puk(char const *, struct umb_parameter *, char const *); +static int _set_roaming_allow(char const *, struct umb_parameter *, + char const *); +static int _set_roaming_deny(char const *, struct umb_parameter *, + char const *); + +static int _umbctl_set(char const * ifname, struct umb_parameter * umbp, + int argc, char * argv[]) +{ + struct + { + char const * name; + int (*callback)(char const *, + struct umb_parameter *, char const *); + int parameter; + } callbacks[] = + { + { "apn", _set_apn, 1 }, + { "username", _set_username, 1 }, + { "password", _set_password, 1 }, + { "pin", _set_pin, 1 }, + { "puk", _set_puk, 1 }, + { "roaming", _set_roaming_allow, 0 }, + { "-roaming", _set_roaming_deny, 0 }, + }; + int i; + size_t j; + + for(i = 0; i < argc; i++) + { + for(j = 0; j < sizeof(callbacks) / sizeof(*callbacks); j++) + if(strcmp(argv[i], callbacks[j].name) == 0) + { + if(callbacks[j].parameter && i + 1 == argc) + return _error(-1, "%s: Incomplete" + " parameter", argv[i]); + if(callbacks[j].callback(ifname, umbp, + callbacks[j].parameter + ? argv[i + 1] : NULL)) + return -1; + if(callbacks[j].parameter) + i++; + break; + } + if(j == sizeof(callbacks) / sizeof(*callbacks)) + return _error(-1, "%s: Unknown parameter", argv[i]); + } + return 0; +} + +static int _set_apn(char const * ifname, struct umb_parameter * umbp, + char const * apn) +{ + umbp->apnlen = _char_to_utf16(apn, umbp->apn, sizeof(umbp->apn)); + if(umbp->apnlen < 0 || (size_t)umbp->apnlen > sizeof(umbp->apn)) + return _error(-1, "%s: %s", ifname, "APN too long"); + return 0; +} + +static int _set_username(char const * ifname, struct umb_parameter * umbp, + char const * username) +{ + umbp->usernamelen = _char_to_utf16(username, umbp->username, + sizeof(umbp->username)); + if(umbp->usernamelen < 0 + || (size_t)umbp->usernamelen > sizeof(umbp->username)) + return _error(-1, "%s: %s", ifname, "Username too long"); + return 0; +} + +static int _set_password(char const * ifname, struct umb_parameter * umbp, + char const * password) +{ + umbp->passwordlen = _char_to_utf16(password, umbp->password, + sizeof(umbp->password)); + if(umbp->passwordlen < 0 + || (size_t)umbp->passwordlen > sizeof(umbp->password)) + return _error(-1, "%s: %s", ifname, "Password too long"); + return 0; +} + +static int _set_pin(char const * ifname, struct umb_parameter * umbp, + char const * pin) +{ + umbp->is_puk = 0; + umbp->op = MBIM_PIN_OP_ENTER; + umbp->pinlen = _char_to_utf16(pin, umbp->pin, sizeof(umbp->pin)); + if(umbp->pinlen < 0 || (size_t)umbp->pinlen + > sizeof(umbp->pin)) + return _error(-1, "%s: %s", ifname, "PIN code too long"); + return 0; +} + +static int _set_puk(char const * ifname, struct umb_parameter * umbp, + char const * puk) +{ + umbp->is_puk = 1; + umbp->op = MBIM_PIN_OP_ENTER; + umbp->pinlen = _char_to_utf16(puk, umbp->pin, sizeof(umbp->pin)); + if(umbp->pinlen < 0 || (size_t)umbp->pinlen > sizeof(umbp->pin)) + return _error(-1, "%s: %s", ifname, "PUK code too long"); + return 0; +} + +static int _set_roaming_allow(char const * ifname, struct umb_parameter * umbp, + char const * unused) +{ + (void) ifname; + (void) unused; + + umbp->roaming = 1; + return 0; +} + +static int _set_roaming_deny(char const * ifname, struct umb_parameter * umbp, + char const * unused) +{ + (void) ifname; + (void) unused; + + umbp->roaming = 0; + return 0; +} + + +/* umbctl_socket */ +static int _umbctl_socket(void) +{ + int fd; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return _error(-1, "socket: %s", strerror(errno)); + return fd; +} + + +/* usage */ +static int _usage(void) +{ + fputs("Usage: umbctl [-v] ifname [parameter [value]] [...]\n" +" umbctl -f config-file ifname\n", + stderr); + return 1; +} + + +/* utf16_to_char */ +static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen) +{ + uint16_t c; + + while (outlen > 0) { + c = inlen > 0 ? htole16(*in) : 0; + if (c == 0 || --outlen == 0) { + /* always NUL terminate result */ + *out = '\0'; + break; + } + *out++ = isascii(c) ? (char)c : '?'; + in++; + inlen--; + } +} + + +/* main */ +int main(int argc, char * argv[]) +{ + int o; + char const * filename = NULL; + int verbose = 0; + + while((o = getopt(argc, argv, "f:gv")) != -1) + switch(o) + { + case 'f': + filename = optarg; + break; + case 'v': + verbose++; + break; + default: + return _usage(); + } + if(optind == argc) + return _usage(); + if(filename != NULL) + { + if(optind + 1 != argc) + return _usage(); + return _umbctl_file(argv[optind], filename, verbose); + } + return _umbctl(argv[optind], verbose, argc - optind - 1, + &argv[optind + 1]); +} diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index c03ba63c349f..9dc1c7f9bc12 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1041,6 +1041,7 @@ MAN+= \ uled.4 \ ulpt.4 \ umass.4 \ + umb.4 \ umcs.4 \ umct.4 \ umodem.4 \ diff --git a/share/man/man4/umb.4 b/share/man/man4/umb.4 new file mode 100644 index 000000000000..b0d517095933 --- /dev/null +++ b/share/man/man4/umb.4 @@ -0,0 +1,119 @@ +.\"- +.\" SPDX-License-Identifier: 0BSD +.\" +.\" Copyright (c) 2016 genua mbH +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $NetBSD: umb.4,v 1.4 2019/08/30 09:22:17 wiz Exp $ +.\" +.Dd August 24, 2019 +.Dt UMB 4 +.Os +.Sh NAME +.Nm umb +.Nd USB Mobile Broadband Interface Model (MBIM) +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device usb" +.Cd "device umb" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +umb_load="YES" +.Ed +.Pp +If neither of the above is done, the driver will automatically be loaded +by devd(8) when the device is connected. +.Sh DESCRIPTION +The +.Nm +driver provides support for USB MBIM devices. +.Pp +MBIM devices establish connections via cellular networks such as +GPRS, UMTS, and LTE. +They appear as a regular point-to-point network interface, +transporting raw IP frames. +.Pp +Required configuration parameters like PIN and APN have to be set +with +.Xr umbctl 8 . +Once the SIM card has been unlocked with the correct PIN, it +will remain in this state until the MBIM device is power-cycled. +In case the device is connected to an "always-on" USB port, +it may be possible to connect to a provider without entering the +PIN again even if the system was rebooted. +.Sh HARDWARE +The +.Nm +driver should support any USB device implementing MBIM, including +the following cellular modems: +.Pp +.Bl -bullet -compact +.It +Ericsson H5321gw and N5321gw +.It +Fibocom L831-EAU +.It +Medion Mobile S4222 (MediaTek OEM) +.It +Sierra Wireless EM7345 +.It +Sierra Wireless EM7455 +.It +Sierra Wireless EM8805 +.It +Sierra Wireless MC8305 +.El +.Sh SEE ALSO +.Xr intro 4 , +.Xr netintro 4 , +.Xr usb 4 , +.Xr ifconfig 8 , +.Xr umbctl 8 +.Rs +.%T "Universal Serial Bus Communications Class Subclass Specification for Mobile Broadband Interface Model" +.%U http://www.usb.org/developers/docs/devclass_docs/MBIM10Errata1_073013.zip +.Re +.Sh HISTORY +The +.Nm +device driver first appeared in +.Ox 6.0 , +.Nx 9.0 , +and +.Fx 15.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Gerhard Roth Aq Mt gerhard@openbsd.org +and ported from +.Ox +by +.An Pierre Pronchery Aq Mt khorben@defora.org . +.Sh CAVEATS +The +.Nm +driver does not support IPv6. +.Pp +Devices which fail to provide a conforming MBIM implementation will +probably be attached as some other driver, such as +.Xr u3g 4 . diff --git a/sys/conf/files b/sys/conf/files index a02174f3d954..5fd7b887581a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3293,6 +3293,7 @@ dev/usb/net/if_muge.c optional muge dev/usb/net/if_rue.c optional rue dev/usb/net/if_smsc.c optional smsc dev/usb/net/if_udav.c optional udav +dev/usb/net/if_umb.c optional umb dev/usb/net/if_ure.c optional ure dev/usb/net/if_usie.c optional usie dev/usb/net/if_urndis.c optional urndis diff --git a/sys/dev/usb/net/if_umb.c b/sys/dev/usb/net/if_umb.c new file mode 100644 index 000000000000..9b2b504cfa6b --- /dev/null +++ b/sys/dev/usb/net/if_umb.c @@ -0,0 +1,2930 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Original copyright (c) 2016 genua mbH (OpenBSD version) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Copyright (c) 2022 ADISTA SAS (re-write for FreeBSD) + * + * Re-write for FreeBSD by Pierre Pronchery + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation *** 4136 LINES SKIPPED ***