Hi, newbie here so please be gentle :-) 

Here's a patch adding FCC unlocking as well as setting up IP addresses and
routes. It eliminates the need of that "horrible python thing". Is anyone
still working on the driver or can I go ahead and try and port the ASN1
thing to the kernel?

On Sat, Jul 10, 2021 at 08:20:11PM +0000, Stuart Henderson wrote:
> On 2021/07/09 17:22, Stuart Henderson wrote:
> > On 2021/07/09 16:33, Stuart Henderson wrote:
> > > Notes so far:
> > > 
> > > > +xmmc*)
> > > > +       dev=${U%.*}
> > > > +       func=${U#*.}
> > > > +       M xmmc$U c 101 $(($(($dev*16))+$func)) 660
> > > > +       ;;
> > > 
> > > "sh MAKEDEV xmmc" isn't enough, it needs "sh MAKEDEV xmmc.0"
> > > 
> > > > +       ret = EIO;
> > > > +       syslog(LOG_ERR, "FCC unlock not implemented, yet");
> > > 
> > > Thus ends my initial experimentation ;)
> > > 
> > 
> > oh; it's just in xmmctl of course! With the horrible python thing, I have
> > a working connection.
> 
> If anyone else wants to play, here's a port roughly based on the one in
> pkgsrc. Obviously not optimal but it is nice to be able to see it working.
> 


--- xmmctl.c.orig       Fri Aug  6 23:52:57 2021
+++ xmmctl.c    Fri Aug  6 23:54:05 2021
@@ -23,6 +23,7 @@
 #include <stdbool.h>
 #include <limits.h>
 #include <assert.h>
+#include <sha2.h>
 #include <stdint.h>
 #include <string.h>
 #include <syslog.h>
@@ -247,7 +248,7 @@
                asn1_buf_reset(&buf);
                ret = read_msg(&buf);
                if (ret != 0)
-                       break;
+                       continue;
                ret = xmm_msg_decode(&buf, msg);
                if (ret != 0) {
                        xmm_msg_release(msg);
@@ -434,7 +435,10 @@
 int
 do_fcc_unlock()
 {
+       SHA2_CTX ctx;
+       struct asn1_buf buf;
        struct xmm_msg msg;
+       uint32_t resp;
        int ret = execute(CsiFccLockQueryReq, NULL, true, &msg, "iii");
 
        if (ret != 0) {
@@ -443,17 +447,65 @@
        }
        /* fcc_mode == 0: No fcc lock required. */
        if (msg.val[2].i == 0) {
+               syslog(LOG_DEBUG, "%s: No FCC lock required", __func__);
                ret = 0;
                goto out;
        }
        /* fcc_state != 0: already unlocked. */
        if (msg.val[1].i != 0) {
+               syslog(LOG_DEBUG, "%s: Already unlocked", __func__);
                ret = 0;
                goto out;
        }
 
-       ret = EIO;
-       syslog(LOG_ERR, "FCC unlock not implemented, yet");
+       ret = execute(CsiFccLockGenChallengeReq, NULL, true, &msg, "ii");
+       if (ret != 0) {
+               syslog(LOG_ERR, "CsiFccLockGenChallengeReq failed with %d", 
ret);
+               return ret;
+       }
+
+       ret = asn1_buf_init(&buf);
+       if (ret != 0)
+               return ret;
+
+       ret = asn1_add_raw_u32(&buf, 0x19c7f83d);
+       if (ret != 0)
+               return ret;
+
+       ret = asn1_add_raw_u32(&buf, msg.val[1].i);
+       if (ret != 0)
+               return ret;
+
+       SHA256Init(&ctx);
+       SHA256Update(&ctx, buf.buf + buf.off, 8);
+
+       asn1_buf_reset(&buf);
+       ret = asn1_buf_pad(&buf, SHA256_DIGEST_LENGTH);
+       if (ret != 0)
+               return ret;
+
+       SHA256Final(buf.buf + buf.off, &ctx);
+       asn1_decode_raw_u32(&buf, &resp);
+
+       asn1_buf_reset(&buf);
+       ret = asn1_add_int32(&buf, resp);
+       if (ret != 0)
+               return ret;
+
+       ret = execute(CsiFccLockVerChallengeReq, &buf, true, &msg, "i");
+       if (ret != 0) {
+               syslog(LOG_ERR, "CsiFccLockVerChallengeReq failed with %d", 
ret);
+               return ret;
+       }
+
+       if (msg.val[0].i != 1) {
+               syslog(LOG_ERR, "FCC unlock failed: %d", ret);
+               return ret;
+       }
+
+       syslog(LOG_DEBUG, "%s: FCC unlocked", __func__);
+
+       ret = 0;
 out:
        xmm_msg_release(&msg);
        return ret;
@@ -764,11 +816,11 @@
 
        *addr = NULL;
 
-       /* XXX assumes that the valid address is followed by 0.0.0.0 */
        for (i = 0; i < count; i++) {
-               if (addrs[i].s_addr == 0)
-                       break;
+               if (addrs[i].s_addr != 0) {
                        *addr = &addrs[i];
+               } else if (*addr)
+                       break;
        }
        if (*addr == NULL)
                return EFAULT;
@@ -813,10 +865,11 @@
        struct in_addr *ip_addrs = NULL;
        const struct in_addr *addr;
        struct dns_addr *dns_servers = NULL;
-       ssize_t ip_count, dns_count;
+       ssize_t ip_count, dns_count, retp_len;
        bool del = false;
        char buf[INET6_ADDRSTRLEN];
        unsigned int iface_num;
+       FILE *resolv_file;
 
        while ((ch = getopt(argc, argv, "a:p:")) != -1) {
                switch (ch) {
@@ -908,25 +961,6 @@
                return 1;
        }
 
-       /*
-        * The value of attach_allowed is unknown at this point.
-        * Try to attach even if not allowed (yet). If this fails
-        * wait for a status change of attach_allowed (as a delayed
-        * result of UtaApnSet()) and try again.
-        */
-       signal(SIGALRM, timeout);
-       alarm(30);
-       while (!attach_allowed && !timed_out) {
-               ret = pump(NULL);
-               if (timed_out || ret == EINTR)
-                       break;
-               if (ret != 0) {
-                       syslog(LOG_ERR, "failed to attach net");
-                       return 1;
-               }
-       }
-       alarm(0);
-       timed_out = false;
        ret = UtaMsNetAttach();
        if (ret != 0) {
                errno = ret;
@@ -945,11 +979,6 @@
                return 1;
        }
 
-       if ((ret = UtaSetupConnection()) != 0) {
-               syslog(LOG_ERR, "failed to set up connection");
-               return 1;
-       }
-
        ret = select_ip_addr(ip_addrs, ip_count, &addr);
        if (ret != 0) {
                syslog(LOG_ERR, "failed to select ip address");
@@ -958,21 +987,45 @@
 
        retp = inet_ntop(AF_INET, addr, buf, sizeof(buf));
        if (retp != NULL) {
-               printf("IP: %s\n", retp);
                syslog(LOG_DEBUG, "got ip addr %s", retp);
+
+               retp_len = strlen(retp);
+               char *cmd = malloc(21 + 2 * retp_len + strlen(ifname));
+               sprintf(cmd, "/sbin/ifconfig %s %s/32 %s", ifname, buf, buf);
+               ret = system(cmd);
+               if (ret != 0) {
+                       syslog(LOG_ERR, "ifconfig failed");
+                       return 1;
                }
 
+               free(cmd);
+               cmd = malloc(37 + retp_len);
+               sprintf(cmd, "/sbin/route add -priority 6 default %s", buf);
+               ret = system(cmd);
+               free(cmd);
+               if (ret != 0) {
+                       syslog(LOG_ERR, "route failed");
+                       return 1;
+               }
+       }
 
-       printf("DNS servers:");
+       if (dns_count > 0) {
+               resolv_file = fopen("/etc/resolv.conf", "w");
+               fprintf(resolv_file, "# Generated by xmmctl\n");
        for (i = 0; i < dns_count; i++) {
                retp = inet_ntop(dns_servers[i].family, &(dns_servers[i].addr4),
                    buf, sizeof(buf));
                if (retp != NULL) {
-                       syslog(LOG_DEBUG, "got dns server %s", retp);
-                       printf(" %s", retp);
+                               fprintf(resolv_file, "nameserver %s\n", buf);
                }
        }
-       printf("\n");
+               fclose(resolv_file);
+       }
+
+       if ((ret = UtaSetupConnection()) != 0) {
+               syslog(LOG_ERR, "failed to set up connection");
+               return 1;
+       }
 
        close(rpcfd);
 

Reply via email to