LCOV - code coverage report
Current view: top level - source3/smbd - avahi_register.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 157 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * Register _smb._tcp with avahi
       4             :  *
       5             :  * Copyright (C) Volker Lendecke 2009
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : 
      24             : #include <avahi-client/client.h>
      25             : #include <avahi-client/publish.h>
      26             : #include <avahi-common/error.h>
      27             : #include <avahi-common/malloc.h>
      28             : #include <avahi-common/strlst.h>
      29             : 
      30             : struct avahi_state_struct {
      31             :         struct AvahiPoll *poll;
      32             :         AvahiClient *client;
      33             :         AvahiEntryGroup *entry_group;
      34             :         uint16_t port;
      35             : };
      36             : 
      37             : static void *avahi_allocator_ctx = NULL;
      38             : 
      39           0 : static void * avahi_allocator_malloc(size_t size)
      40             : {
      41           0 :         return talloc_size(avahi_allocator_ctx, size);
      42             : }
      43             : 
      44           0 : static void avahi_allocator_free(void *p)
      45             : {
      46           0 :         TALLOC_FREE(p);
      47           0 : }
      48             : 
      49           0 : static void * avahi_allocator_realloc(void *p, size_t size)
      50             : {
      51           0 :         return talloc_realloc_size(avahi_allocator_ctx, p, size);
      52             : }
      53             : 
      54           0 : static void * avahi_allocator_calloc(size_t count, size_t size)
      55             : {
      56           0 :         void *p = talloc_array_size(avahi_allocator_ctx, size, count);
      57           0 :         if (p) {
      58           0 :                 memset(p, 0, size * count);
      59             :         }
      60           0 :         return p;
      61             : }
      62             : 
      63             : static const struct AvahiAllocator avahi_talloc_allocator = {
      64             :         &avahi_allocator_malloc,
      65             :         &avahi_allocator_free,
      66             :         &avahi_allocator_realloc,
      67             :         &avahi_allocator_calloc
      68             : };
      69             : 
      70           0 : static void avahi_entry_group_callback(AvahiEntryGroup *g,
      71             :                                        AvahiEntryGroupState status,
      72             :                                        void *userdata)
      73             : {
      74           0 :         struct avahi_state_struct *state = talloc_get_type_abort(
      75             :                 userdata, struct avahi_state_struct);
      76             :         int error;
      77             : 
      78           0 :         switch (status) {
      79           0 :         case AVAHI_ENTRY_GROUP_ESTABLISHED:
      80           0 :                 DBG_DEBUG("AVAHI_ENTRY_GROUP_ESTABLISHED\n");
      81           0 :                 break;
      82           0 :         case AVAHI_ENTRY_GROUP_FAILURE:
      83           0 :                 error = avahi_client_errno(state->client);
      84             : 
      85           0 :                 DBG_DEBUG("AVAHI_ENTRY_GROUP_FAILURE: %s\n",
      86             :                           avahi_strerror(error));
      87           0 :                 break;
      88           0 :         case AVAHI_ENTRY_GROUP_COLLISION:
      89           0 :                 DBG_DEBUG("AVAHI_ENTRY_GROUP_COLLISION\n");
      90           0 :                 break;
      91           0 :         case AVAHI_ENTRY_GROUP_UNCOMMITED:
      92           0 :                 DBG_DEBUG("AVAHI_ENTRY_GROUP_UNCOMMITED\n");
      93           0 :                 break;
      94           0 :         case AVAHI_ENTRY_GROUP_REGISTERING:
      95           0 :                 DBG_DEBUG("AVAHI_ENTRY_GROUP_REGISTERING\n");
      96           0 :                 break;
      97             :         }
      98           0 : }
      99             : 
     100           0 : static void avahi_client_callback(AvahiClient *c, AvahiClientState status,
     101             :                                   void *userdata)
     102             : {
     103           0 :         struct avahi_state_struct *state = talloc_get_type_abort(
     104             :                 userdata, struct avahi_state_struct);
     105             :         int error;
     106             : 
     107           0 :         switch (status) {
     108           0 :         case AVAHI_CLIENT_S_RUNNING: {
     109             :                 int snum;
     110           0 :                 int num_services = lp_numservices();
     111           0 :                 size_t dk = 0;
     112           0 :                 AvahiStringList *adisk = NULL;
     113           0 :                 AvahiStringList *adisk2 = NULL;
     114           0 :                 AvahiStringList *dinfo = NULL;
     115           0 :                 const char *hostname = NULL;
     116           0 :                 enum mdns_name_values mdns_name = lp_mdns_name();
     117           0 :                 const char *model = NULL;
     118             : 
     119           0 :                 DBG_DEBUG("AVAHI_CLIENT_S_RUNNING\n");
     120             : 
     121             :                 switch (mdns_name) {
     122           0 :                 case MDNS_NAME_MDNS:
     123           0 :                         hostname = avahi_client_get_host_name(c);
     124           0 :                         break;
     125           0 :                 case MDNS_NAME_NETBIOS:
     126           0 :                         hostname = lp_netbios_name();
     127           0 :                         break;
     128           0 :                 default:
     129           0 :                         DBG_ERR("Unhandled mdns_name %d\n", mdns_name);
     130           0 :                         return;
     131             :                 }
     132             : 
     133           0 :                 state->entry_group = avahi_entry_group_new(
     134             :                         c, avahi_entry_group_callback, state);
     135           0 :                 if (state->entry_group == NULL) {
     136           0 :                         error = avahi_client_errno(c);
     137           0 :                         DBG_DEBUG("avahi_entry_group_new failed: %s\n",
     138             :                                   avahi_strerror(error));
     139           0 :                         break;
     140             :                 }
     141             : 
     142           0 :                 error = avahi_entry_group_add_service(
     143             :                             state->entry_group, AVAHI_IF_UNSPEC,
     144             :                             AVAHI_PROTO_UNSPEC, 0, hostname,
     145           0 :                             "_smb._tcp", NULL, NULL, state->port, NULL);
     146           0 :                 if (error != AVAHI_OK) {
     147           0 :                         DBG_DEBUG("avahi_entry_group_add_service failed: %s\n",
     148             :                                   avahi_strerror(error));
     149           0 :                         avahi_entry_group_free(state->entry_group);
     150           0 :                         state->entry_group = NULL;
     151           0 :                         break;
     152             :                 }
     153             : 
     154           0 :                 for (snum = 0; snum < num_services; snum++) {
     155           0 :                         if (lp_snum_ok(snum) &&
     156           0 :                             lp_parm_bool(snum, "fruit", "time machine", false))
     157             :                         {
     158           0 :                                 adisk2 = avahi_string_list_add_printf(
     159             :                                             adisk, "dk%zu=adVN=%s,adVF=0x82",
     160             :                                             dk++, lp_const_servicename(snum));
     161           0 :                                 if (adisk2 == NULL) {
     162           0 :                                         DBG_DEBUG("avahi_string_list_add_printf"
     163             :                                                   "failed: returned NULL\n");
     164           0 :                                         avahi_string_list_free(adisk);
     165           0 :                                         avahi_entry_group_free(state->entry_group);
     166           0 :                                         state->entry_group = NULL;
     167           0 :                                         break;
     168             :                                 }
     169           0 :                                 adisk = adisk2;
     170           0 :                                 adisk2 = NULL;
     171             :                         }
     172             :                 }
     173           0 :                 if (dk > 0) {
     174           0 :                         adisk2 = avahi_string_list_add(adisk, "sys=adVF=0x100");
     175           0 :                         if (adisk2 == NULL) {
     176           0 :                                 DBG_DEBUG("avahi_string_list_add failed: "
     177             :                                           "returned NULL\n");
     178           0 :                                 avahi_string_list_free(adisk);
     179           0 :                                 avahi_entry_group_free(state->entry_group);
     180           0 :                                 state->entry_group = NULL;
     181           0 :                                 break;
     182             :                         }
     183           0 :                         adisk = adisk2;
     184           0 :                         adisk2 = NULL;
     185             : 
     186           0 :                         error = avahi_entry_group_add_service_strlst(
     187             :                                     state->entry_group, AVAHI_IF_UNSPEC,
     188             :                                     AVAHI_PROTO_UNSPEC, 0, hostname,
     189             :                                     "_adisk._tcp", NULL, NULL, 0, adisk);
     190           0 :                         avahi_string_list_free(adisk);
     191           0 :                         adisk = NULL;
     192           0 :                         if (error != AVAHI_OK) {
     193           0 :                                 DBG_DEBUG("avahi_entry_group_add_service_strlst "
     194             :                                           "failed: %s\n", avahi_strerror(error));
     195           0 :                                 avahi_entry_group_free(state->entry_group);
     196           0 :                                 state->entry_group = NULL;
     197           0 :                                 break;
     198             :                         }
     199             :                 }
     200             : 
     201           0 :                 model = lp_parm_const_string(-1, "fruit", "model", "MacSamba");
     202             : 
     203           0 :                 dinfo = avahi_string_list_add_printf(NULL, "model=%s", model);
     204           0 :                 if (dinfo == NULL) {
     205           0 :                         DBG_DEBUG("avahi_string_list_add_printf"
     206             :                                   "failed: returned NULL\n");
     207           0 :                         avahi_entry_group_free(state->entry_group);
     208           0 :                         state->entry_group = NULL;
     209           0 :                         break;
     210             :                 }
     211             : 
     212           0 :                 error = avahi_entry_group_add_service_strlst(
     213             :                             state->entry_group, AVAHI_IF_UNSPEC,
     214             :                             AVAHI_PROTO_UNSPEC, 0, hostname,
     215             :                             "_device-info._tcp", NULL, NULL, 0,
     216             :                             dinfo);
     217           0 :                 avahi_string_list_free(dinfo);
     218           0 :                 if (error != AVAHI_OK) {
     219           0 :                         DBG_DEBUG("avahi_entry_group_add_service failed: %s\n",
     220             :                                   avahi_strerror(error));
     221           0 :                         avahi_entry_group_free(state->entry_group);
     222           0 :                         state->entry_group = NULL;
     223           0 :                         break;
     224             :                 }
     225             : 
     226           0 :                 error = avahi_entry_group_commit(state->entry_group);
     227           0 :                 if (error != AVAHI_OK) {
     228           0 :                         DBG_DEBUG("avahi_entry_group_commit failed: %s\n",
     229             :                                   avahi_strerror(error));
     230           0 :                         avahi_entry_group_free(state->entry_group);
     231           0 :                         state->entry_group = NULL;
     232           0 :                         break;
     233             :                 }
     234           0 :                 break;
     235             :         }
     236           0 :         case AVAHI_CLIENT_FAILURE:
     237           0 :                 error = avahi_client_errno(c);
     238             : 
     239           0 :                 DBG_DEBUG("AVAHI_CLIENT_FAILURE: %s\n", avahi_strerror(error));
     240             : 
     241           0 :                 if (error != AVAHI_ERR_DISCONNECTED) {
     242           0 :                         break;
     243             :                 }
     244           0 :                 avahi_client_free(c);
     245           0 :                 state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
     246             :                                                  avahi_client_callback, state,
     247             :                                                  &error);
     248           0 :                 if (state->client == NULL) {
     249           0 :                         DBG_DEBUG("avahi_client_new failed: %s\n",
     250             :                                   avahi_strerror(error));
     251           0 :                         break;
     252             :                 }
     253           0 :                 break;
     254           0 :         case AVAHI_CLIENT_S_COLLISION:
     255           0 :                 DBG_DEBUG("AVAHI_CLIENT_S_COLLISION\n");
     256           0 :                 break;
     257           0 :         case AVAHI_CLIENT_S_REGISTERING:
     258           0 :                 DBG_DEBUG("AVAHI_CLIENT_S_REGISTERING\n");
     259           0 :                 break;
     260           0 :         case AVAHI_CLIENT_CONNECTING:
     261           0 :                 DBG_DEBUG("AVAHI_CLIENT_CONNECTING\n");
     262           0 :                 break;
     263             :         }
     264             : }
     265             : 
     266           0 : void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     267             :                            uint16_t port)
     268             : {
     269             :         struct avahi_state_struct *state;
     270             :         int error;
     271             : 
     272           0 :         avahi_allocator_ctx = talloc_new(mem_ctx);
     273           0 :         if (avahi_allocator_ctx == NULL) {
     274           0 :                 return NULL;
     275             :         }
     276           0 :         avahi_set_allocator(&avahi_talloc_allocator);
     277             : 
     278           0 :         state = talloc(mem_ctx, struct avahi_state_struct);
     279           0 :         if (state == NULL) {
     280           0 :                 return state;
     281             :         }
     282           0 :         state->port = port;
     283           0 :         state->poll = tevent_avahi_poll(state, ev);
     284           0 :         if (state->poll == NULL) {
     285           0 :                 goto fail;
     286             :         }
     287           0 :         state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
     288             :                                          avahi_client_callback, state,
     289             :                                          &error);
     290           0 :         if (state->client == NULL) {
     291           0 :                 DBG_DEBUG("avahi_client_new failed: %s\n",
     292             :                           avahi_strerror(error));
     293           0 :                 goto fail;
     294             :         }
     295           0 :         return state;
     296             : 
     297           0 :  fail:
     298           0 :         TALLOC_FREE(state);
     299           0 :         return NULL;
     300             : }

Generated by: LCOV version 1.14