Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1 /* thread-service.c
      2  *
      3  * Copyright (c) 2023 Apple Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     https://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  * Manage Thread service objects
     18  */
     19 
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <stdio.h>
     23 #include <unistd.h>
     24 #include <pwd.h>
     25 #include <errno.h>
     26 #include <sys/socket.h>
     27 #include <netinet/in.h>
     28 #include <arpa/inet.h>
     29 #include <fcntl.h>
     30 #include <time.h>
     31 #include <dns_sd.h>
     32 #include <net/if.h>
     33 #include <inttypes.h>
     34 #include <sys/resource.h>
     35 #include <netinet/icmp6.h>
     36 #include "srp.h"
     37 #include "dns-msg.h"
     38 #include "srp-crypto.h"
     39 #include "ioloop.h"
     40 #include "srp-mdns-proxy.h"
     41 #include "dnssd-proxy.h"
     42 #include "srp-gw.h"
     43 #include "srp-proxy.h"
     44 #include "config-parse.h"
     45 #include "cti-services.h"
     46 #include "thread-device.h"
     47 #include "state-machine.h"
     48 #include "thread-service.h"
     49 
     50 const char *
     51 thread_service_publication_state_name_get(thread_service_publication_state_t publication_state)
     52 {
     53     switch (publication_state) {
     54     default:
     55         return "<unknown>";
     56     case add_complete:
     57         return "add_complete";
     58     case delete_complete:
     59         return "delete_complete";
     60     case add_failed:
     61         return "add_failed";
     62     case delete_failed:
     63         return "delete_failed";
     64     case add_pending:
     65         return "add_pending";
     66     case delete_pending:
     67         return "delete_pending";
     68     case want_add:
     69         return "want_add";
     70     case want_delete:
     71         return "want_delete";
     72     }
     73 }
     74 
     75 static void
     76 thread_service_finalize(thread_service_t *service)
     77 {
     78     free(service);
     79 }
     80 
     81 RELEASE_RETAIN_FUNCS(thread_service);
     82 
     83 void
     84 thread_service_list_release(thread_service_t **list_pointer)
     85 {
     86     while (*list_pointer != NULL) {
     87         thread_service_t *service = *list_pointer;
     88         *list_pointer = service->next;
     89         RELEASE_HERE(service, thread_service);
     90     }
     91 }
     92 
     93 thread_service_t *
     94 thread_service_unicast_create_(uint16_t rloc16, uint8_t *address, uint8_t *port, uint8_t service_id, const char *file, int line)
     95 {
     96     thread_service_t *service;
     97 
     98     service = calloc(1, sizeof(*service));
     99     if (service != NULL) {
    100         in6prefix_copy_from_data(&service->u.unicast.address, address, sizeof(service->u.unicast.address));
    101         memcpy(&service->u.unicast.port, port, 2);
    102         service->rloc16 = rloc16;
    103         service->service_type = unicast_service;
    104         service->service_id = service_id;
    105         RETAIN(service, thread_service);
    106     }
    107     return service;
    108 }
    109 
    110 thread_service_t *
    111 thread_service_anycast_create_(uint16_t rloc16, uint8_t sequence_number, uint8_t service_id, const char *file, int line)
    112 {
    113     thread_service_t *service;
    114 
    115     service = calloc(1, sizeof(*service));
    116     if (service != NULL) {
    117         service->rloc16 = rloc16;
    118         service->u.anycast.sequence_number = sequence_number;
    119         service->service_type = anycast_service;
    120         service->service_id = service_id;
    121         RETAIN(service, thread_service);
    122     }
    123     return service;
    124 }
    125 
    126 thread_service_t *
    127 thread_service_pref_id_create_(uint16_t rloc16, uint8_t *partition_id, uint8_t *prefix, uint8_t service_id, const char *file, int line)
    128 {
    129     thread_service_t *service;
    130 
    131     service = calloc(1, sizeof(*service));
    132     if (service != NULL) {
    133         service->rloc16 = rloc16;
    134         memcpy(&service->u.pref_id.partition_id, partition_id, 4);
    135         memcpy(&service->u.pref_id.prefix, prefix, 5);
    136         service->service_type = pref_id;
    137         service->service_id = service_id;
    138         RETAIN(service, thread_service);
    139     }
    140     return service;
    141 }
    142 
    143 void
    144 thread_service_note(const char *owner_id, thread_service_t *tservice, const char *event_description)
    145 {
    146     switch(tservice->service_type) {
    147     default:
    148         INFO("invalid service type %d on service %p", tservice->service_type, tservice);
    149         break;
    150     case unicast_service:
    151         {
    152             struct thread_unicast_service *service = &tservice->u.unicast;
    153             uint16_t port;
    154 
    155             port = (uint16_t)(service->port[0] << 8) | service->port[1];
    156             SEGMENTED_IPv6_ADDR_GEN_SRP(&service->address, service_add_buf);
    157             INFO(PUB_S_SRP " SRP service " PRI_SEGMENTED_IPv6_ADDR_SRP "%%%d, rloc16 %x " PUB_S_SRP, owner_id,
    158                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&service->address, service_add_buf),
    159                  port, tservice->rloc16, event_description);
    160         }
    161         break;
    162     case anycast_service:
    163         {
    164             struct thread_anycast_service *service = &tservice->u.anycast;
    165             INFO(PUB_S_SRP " SRP service on RLOC16 %x with sequence number %02x "  PUB_S_SRP, owner_id,
    166                  tservice->rloc16, service->sequence_number, event_description);
    167         }
    168         break;
    169     case pref_id:
    170         {
    171             struct thread_pref_id *pref_id = &tservice->u.pref_id;
    172             struct in6_addr addr;
    173 
    174             addr.s6_addr[0] = 0xfd;
    175             memcpy(&addr.s6_addr[1], pref_id->prefix, 5);
    176             memset(&addr.s6_addr[6], 0, 10);
    177             SEGMENTED_IPv6_ADDR_GEN_SRP(addr.s6_addr, addr_buf);
    178             INFO(PUB_S_SRP " pref:id " PRI_SEGMENTED_IPv6_ADDR_SRP ":%02x%02x%02x%02x rloc %x " PUB_S_SRP, owner_id,
    179                  SEGMENTED_IPv6_ADDR_PARAM_SRP(addr.s6_addr, addr_buf),
    180                  pref_id->partition_id[0], pref_id->partition_id[1], pref_id->partition_id[2], pref_id->partition_id[3],
    181                  tservice->rloc16, event_description);
    182         }
    183         break;
    184     }
    185 }
    186 
    187 bool
    188 thread_service_equal(thread_service_t *a, thread_service_t *b)
    189 {
    190     if (a == NULL || b == NULL) {
    191         return false;
    192     }
    193     if (a->service_type != b->service_type) {
    194         return false;
    195     }
    196     switch(a->service_type) {
    197     default:
    198         return false;
    199     case unicast_service:
    200         {
    201             return (!in6addr_compare(&a->u.unicast.address, &b->u.unicast.address) &&
    202                     !memcmp(a->u.unicast.port, b->u.unicast.port, 2));
    203         }
    204         break;
    205     case anycast_service:
    206         {
    207             return a->u.anycast.sequence_number == b->u.anycast.sequence_number;
    208         }
    209         break;
    210     case pref_id:
    211         {
    212             return false;
    213         }
    214         break;
    215     }
    216     return false;
    217 }
    218 
    219 // Local Variables:
    220 // mode: C
    221 // tab-width: 4
    222 // c-file-style: "bsd"
    223 // c-basic-offset: 4
    224 // fill-column: 120
    225 // indent-tabs-mode: nil
    226 // End:
    227