|
|
|
|
@@ -0,0 +1,430 @@
|
|
|
|
|
From b2d2f9a9a0581c40780bde509f7cc715920f1c02 Mon Sep 17 00:00:00 2001
|
|
|
|
|
From: Denis Ovsienko <denis@ovsienko.info>
|
|
|
|
|
Date: Fri, 19 Dec 2025 17:31:13 +0000
|
|
|
|
|
Subject: [PATCH] CVE-2025-11961: Fix OOBR and OOBW in pcap_ether_aton().
|
|
|
|
|
|
|
|
|
|
pcap_ether_aton() has for a long time required its string argument to be
|
|
|
|
|
a well-formed MAC-48 address, which is always the case when the argument
|
|
|
|
|
comes from other libpcap code, so the function has never validated the
|
|
|
|
|
input and used a simple loop to parse any of the three common MAC-48
|
|
|
|
|
address formats. However, the function has also been a part of the
|
|
|
|
|
public API, so calling it directly with a malformed address can cause
|
|
|
|
|
the loop to read beyond the end of the input string and/or to write
|
|
|
|
|
beyond the end of the allocated output buffer.
|
|
|
|
|
|
|
|
|
|
To handle invalid input more appropriately, replace the simple loop with
|
|
|
|
|
new functions and require the input to match a supported address format.
|
|
|
|
|
|
|
|
|
|
This problem was reported by Jin Wei, Kunwei Qian and Ping Chen.
|
|
|
|
|
|
|
|
|
|
(backported from commit dd08e53e9380e217ae7c7768da9cc3d7bf37bf83)
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
gencode.c | 5 +
|
|
|
|
|
nametoaddr.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++----
|
|
|
|
|
3 files changed, 350 insertions(+), 23 deletions(-)
|
|
|
|
|
|
|
|
|
|
Index: libpcap-1.10.5/gencode.c
|
|
|
|
|
===================================================================
|
|
|
|
|
--- libpcap-1.10.5.orig/gencode.c
|
|
|
|
|
+++ libpcap-1.10.5/gencode.c
|
|
|
|
|
@@ -7501,6 +7501,11 @@ gen_ecode(compiler_state_t *cstate, cons
|
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
|
|
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Because the lexer guards the input string format, in this
|
|
|
|
|
+ * context the function returns NULL iff the implicit malloc()
|
|
|
|
|
+ * has failed.
|
|
|
|
|
+ */
|
|
|
|
|
cstate->e = pcap_ether_aton(s);
|
|
|
|
|
if (cstate->e == NULL)
|
|
|
|
|
bpf_error(cstate, "malloc");
|
|
|
|
|
Index: libpcap-1.10.5/nametoaddr.c
|
|
|
|
|
===================================================================
|
|
|
|
|
--- libpcap-1.10.5.orig/nametoaddr.c
|
|
|
|
|
+++ libpcap-1.10.5/nametoaddr.c
|
|
|
|
|
@@ -696,39 +696,361 @@ __pcap_atodn(const char *s, bpf_u_int32
|
|
|
|
|
return(32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Man page: "xxxxxxxxxxxx", regexp: "^[0-9a-fA-F]{12}$".
|
|
|
|
|
+static u_char
|
|
|
|
|
+pcapint_atomac48_xxxxxxxxxxxx(const char *s, uint8_t *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ if (strlen(s) == 12 &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[0]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[1]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[2]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[3]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[4]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[5]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[6]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[7]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[8]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[9]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[10]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[11])) {
|
|
|
|
|
+ addr[0] = xdtoi(s[0]) << 4 | xdtoi(s[1]);
|
|
|
|
|
+ addr[1] = xdtoi(s[2]) << 4 | xdtoi(s[3]);
|
|
|
|
|
+ addr[2] = xdtoi(s[4]) << 4 | xdtoi(s[5]);
|
|
|
|
|
+ addr[3] = xdtoi(s[6]) << 4 | xdtoi(s[7]);
|
|
|
|
|
+ addr[4] = xdtoi(s[8]) << 4 | xdtoi(s[9]);
|
|
|
|
|
+ addr[5] = xdtoi(s[10]) << 4 | xdtoi(s[11]);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Man page: "xxxx.xxxx.xxxx", regexp: "^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$".
|
|
|
|
|
+static u_char
|
|
|
|
|
+pcapint_atomac48_xxxx_3_times(const char *s, uint8_t *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ const char sep = '.';
|
|
|
|
|
+ if (strlen(s) == 14 &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[0]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[1]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[2]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[3]) &&
|
|
|
|
|
+ s[4] == sep &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[5]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[6]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[7]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[8]) &&
|
|
|
|
|
+ s[9] == sep &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[10]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[11]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[12]) &&
|
|
|
|
|
+ PCAP_ISXDIGIT(s[13])) {
|
|
|
|
|
+ addr[0] = xdtoi(s[0]) << 4 | xdtoi(s[1]);
|
|
|
|
|
+ addr[1] = xdtoi(s[2]) << 4 | xdtoi(s[3]);
|
|
|
|
|
+ addr[2] = xdtoi(s[5]) << 4 | xdtoi(s[6]);
|
|
|
|
|
+ addr[3] = xdtoi(s[7]) << 4 | xdtoi(s[8]);
|
|
|
|
|
+ addr[4] = xdtoi(s[10]) << 4 | xdtoi(s[11]);
|
|
|
|
|
+ addr[5] = xdtoi(s[12]) << 4 | xdtoi(s[13]);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/*
|
|
|
|
|
- * Convert 's', which can have the one of the forms:
|
|
|
|
|
+ * Man page: "xx:xx:xx:xx:xx:xx", regexp: "^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$".
|
|
|
|
|
+ * Man page: "xx-xx-xx-xx-xx-xx", regexp: "^[0-9a-fA-F]{1,2}(-[0-9a-fA-F]{1,2}){5}$".
|
|
|
|
|
+ * Man page: "xx.xx.xx.xx.xx.xx", regexp: "^[0-9a-fA-F]{1,2}(\.[0-9a-fA-F]{1,2}){5}$".
|
|
|
|
|
+ * (Any "xx" above can be "x", which is equivalent to "0x".)
|
|
|
|
|
+ *
|
|
|
|
|
+ * An equivalent (and parametrisable for EUI-64) FSM could be implemented using
|
|
|
|
|
+ * a smaller graph, but that graph would be neither acyclic nor planar nor
|
|
|
|
|
+ * trivial to verify.
|
|
|
|
|
*
|
|
|
|
|
- * "xx:xx:xx:xx:xx:xx"
|
|
|
|
|
- * "xx.xx.xx.xx.xx.xx"
|
|
|
|
|
- * "xx-xx-xx-xx-xx-xx"
|
|
|
|
|
- * "xxxx.xxxx.xxxx"
|
|
|
|
|
- * "xxxxxxxxxxxx"
|
|
|
|
|
+ * |
|
|
|
|
|
+ * [.] v
|
|
|
|
|
+ * +<---------- START
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE0_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE0_XX | [:\.-]
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [:\.-] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<----- BYTE0_SEP_BYTE1 <-----+
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE1_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE1_XX | <sep>
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | <sep> |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<----- BYTE1_SEP_BYTE2 <-----+
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE2_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE2_XX | <sep>
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | <sep> |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<----- BYTE2_SEP_BYTE3 <-----+
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE3_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE3_XX | <sep>
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | <sep> |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<----- BYTE3_SEP_BYTE4 <-----+
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE4_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE4_XX | <sep>
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | <sep> |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<----- BYTE4_SEP_BYTE5 <-----+
|
|
|
|
|
+ * | |
|
|
|
|
|
+ * | | [0-9a-fA-F]
|
|
|
|
|
+ * | [.] v
|
|
|
|
|
+ * +<--------- BYTE5_X ----------+
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | [0-9a-fA-F] |
|
|
|
|
|
+ * | [.] v |
|
|
|
|
|
+ * +<--------- BYTE5_XX | \0
|
|
|
|
|
+ * | | |
|
|
|
|
|
+ * | | \0 |
|
|
|
|
|
+ * | | v
|
|
|
|
|
+ * +--> (reject) +---------> (accept)
|
|
|
|
|
*
|
|
|
|
|
- * (or various mixes of ':', '.', and '-') into a new
|
|
|
|
|
- * ethernet address. Assumes 's' is well formed.
|
|
|
|
|
+ */
|
|
|
|
|
+static u_char
|
|
|
|
|
+pcapint_atomac48_x_xx_6_times(const char *s, uint8_t *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ enum {
|
|
|
|
|
+ START,
|
|
|
|
|
+ BYTE0_X,
|
|
|
|
|
+ BYTE0_XX,
|
|
|
|
|
+ BYTE0_SEP_BYTE1,
|
|
|
|
|
+ BYTE1_X,
|
|
|
|
|
+ BYTE1_XX,
|
|
|
|
|
+ BYTE1_SEP_BYTE2,
|
|
|
|
|
+ BYTE2_X,
|
|
|
|
|
+ BYTE2_XX,
|
|
|
|
|
+ BYTE2_SEP_BYTE3,
|
|
|
|
|
+ BYTE3_X,
|
|
|
|
|
+ BYTE3_XX,
|
|
|
|
|
+ BYTE3_SEP_BYTE4,
|
|
|
|
|
+ BYTE4_X,
|
|
|
|
|
+ BYTE4_XX,
|
|
|
|
|
+ BYTE4_SEP_BYTE5,
|
|
|
|
|
+ BYTE5_X,
|
|
|
|
|
+ BYTE5_XX,
|
|
|
|
|
+ } fsm_state = START;
|
|
|
|
|
+ uint8_t buf[6];
|
|
|
|
|
+ const char *seplist = ":.-";
|
|
|
|
|
+ char sep;
|
|
|
|
|
+
|
|
|
|
|
+ while (*s) {
|
|
|
|
|
+ switch (fsm_state) {
|
|
|
|
|
+ case START:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[0] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE0_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE0_X:
|
|
|
|
|
+ if (strchr(seplist, *s)) {
|
|
|
|
|
+ sep = *s;
|
|
|
|
|
+ fsm_state = BYTE0_SEP_BYTE1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[0] = buf[0] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE0_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE0_XX:
|
|
|
|
|
+ if (strchr(seplist, *s)) {
|
|
|
|
|
+ sep = *s;
|
|
|
|
|
+ fsm_state = BYTE0_SEP_BYTE1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE0_SEP_BYTE1:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[1] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE1_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE1_X:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE1_SEP_BYTE2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[1] = buf[1] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE1_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE1_XX:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE1_SEP_BYTE2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE1_SEP_BYTE2:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[2] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE2_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE2_X:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE2_SEP_BYTE3;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[2] = buf[2] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE2_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE2_XX:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE2_SEP_BYTE3;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE2_SEP_BYTE3:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[3] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE3_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE3_X:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE3_SEP_BYTE4;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[3] = buf[3] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE3_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE3_XX:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE3_SEP_BYTE4;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE3_SEP_BYTE4:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[4] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE4_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE4_X:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE4_SEP_BYTE5;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[4] = buf[4] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE4_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE4_XX:
|
|
|
|
|
+ if (*s == sep) {
|
|
|
|
|
+ fsm_state = BYTE4_SEP_BYTE5;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE4_SEP_BYTE5:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[5] = xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE5_X;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE5_X:
|
|
|
|
|
+ if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
+ buf[5] = buf[5] << 4 | xdtoi(*s);
|
|
|
|
|
+ fsm_state = BYTE5_XX;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ case BYTE5_XX:
|
|
|
|
|
+ goto reject;
|
|
|
|
|
+ } // switch
|
|
|
|
|
+ s++;
|
|
|
|
|
+ } // while
|
|
|
|
|
+
|
|
|
|
|
+ if (fsm_state == BYTE5_X || fsm_state == BYTE5_XX) {
|
|
|
|
|
+ // accept
|
|
|
|
|
+ memcpy(addr, buf, sizeof(buf));
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+reject:
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// The 'addr' argument must point to an array of at least 6 elements.
|
|
|
|
|
+static int
|
|
|
|
|
+pcapint_atomac48(const char *s, uint8_t *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ return s && (
|
|
|
|
|
+ pcapint_atomac48_xxxxxxxxxxxx(s, addr) ||
|
|
|
|
|
+ pcapint_atomac48_xxxx_3_times(s, addr) ||
|
|
|
|
|
+ pcapint_atomac48_x_xx_6_times(s, addr)
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * If 's' is a MAC-48 address in one of the forms documented in pcap-filter(7)
|
|
|
|
|
+ * for "ether host", return a pointer to an allocated buffer with the binary
|
|
|
|
|
+ * value of the address. Return NULL on any error.
|
|
|
|
|
*/
|
|
|
|
|
u_char *
|
|
|
|
|
pcap_ether_aton(const char *s)
|
|
|
|
|
{
|
|
|
|
|
- register u_char *ep, *e;
|
|
|
|
|
- register u_char d;
|
|
|
|
|
+ uint8_t tmp[6];
|
|
|
|
|
+ if (! pcapint_atomac48(s, tmp))
|
|
|
|
|
+ return (NULL);
|
|
|
|
|
|
|
|
|
|
- e = ep = (u_char *)malloc(6);
|
|
|
|
|
+ u_char *e = malloc(6);
|
|
|
|
|
if (e == NULL)
|
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
|
|
- while (*s) {
|
|
|
|
|
- if (*s == ':' || *s == '.' || *s == '-')
|
|
|
|
|
- s += 1;
|
|
|
|
|
- d = xdtoi(*s++);
|
|
|
|
|
- if (PCAP_ISXDIGIT(*s)) {
|
|
|
|
|
- d <<= 4;
|
|
|
|
|
- d |= xdtoi(*s++);
|
|
|
|
|
- }
|
|
|
|
|
- *ep++ = d;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
+ memcpy(e, tmp, sizeof(tmp));
|
|
|
|
|
return (e);
|
|
|
|
|
}
|
|
|
|
|
|