/* accept the socket and do a little sanity checking */ static int dsi_tcp_open(DSI *dsi) { pid_t pid; SOCKLEN_T len; len = sizeof(dsi->client); dsi->socket = accept(dsi->serversock, (struct sockaddr *) &dsi->client, &len); #ifdef TCPWRAP { struct request_info req; request_init(&req, RQ_DAEMON, dsi->program, RQ_FILE, dsi->socket, NULL); fromhost(&req); if (!hosts_access(&req)) { LOG(deny_severity, logtype_dsi, "refused connect from %s", eval_client(&req)); close(dsi->socket); errno = ECONNREFUSED; dsi->socket = -1; } } #endif /* TCPWRAP */ if (dsi->socket < 0) return -1; getitimer(ITIMER_PROF, &itimer); if (0 == (pid = fork()) ) { /* child */ static struct itimerval timer = {{0, 0}, {DSI_TCPTIMEOUT, 0}}; struct sigaction newact, oldact; u_int8_t block[DSI_BLOCKSIZ]; size_t stored; /* Immediateyl mark globally that we're a child now */ parent_or_child = 1; /* reset signals */ server_reset_signal(); #ifndef DEBUGGING /* install an alarm to deal with non-responsive connections */ newact.sa_handler = timeout_handler; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigemptyset(&oldact.sa_mask); oldact.sa_flags = 0; setitimer(ITIMER_PROF, &itimer, NULL); if ((sigaction(SIGALRM, &newact, &oldact) < 0) || (setitimer(ITIMER_REAL, &timer, NULL) < 0)) { LOG(log_error, logtype_dsi, "dsi_tcp_open: %s", strerror(errno)); exit(EXITERR_SYS); } #endif /* read in commands. this is similar to dsi_receive except * for the fact that we do some sanity checking to prevent * delinquent connections from causing mischief. */ /* read in the first two bytes */ len = dsi_stream_read(dsi, block, 2); if (!len ) { /* connection already closed, don't log it (normal OSX 10.3 behaviour) */ exit(EXITERR_CLNT); } if (len < 2 || (block[0] > DSIFL_MAX) || (block[1] > DSIFUNC_MAX)) { LOG(log_error, logtype_dsi, "dsi_tcp_open: invalid header"); exit(EXITERR_CLNT); } /* read in the rest of the header */ stored = 2; while (stored < DSI_BLOCKSIZ) { len = dsi_stream_read(dsi, block + stored, sizeof(block) - stored); if (len > 0) stored += len; else { LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); exit(EXITERR_CLNT); } } dsi->header.dsi_flags = block[0]; dsi->header.dsi_command = block[1]; memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID)); memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code)); memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len)); memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved)); dsi->clientID = ntohs(dsi->header.dsi_requestID); /* make sure we don't over-write our buffers. */ dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ); stored = 0; while (stored < dsi->cmdlen) { len = dsi_stream_read(dsi, dsi->commands + stored, dsi->cmdlen - stored); if (len > 0) stored += len; else { LOG(log_error, logtype_dsi, "dsi_tcp_open: stream_read: %s", strerror(errno)); exit(EXITERR_CLNT); } } /* stop timer and restore signal handler */ #ifndef DEBUGGING memset(&timer, 0, sizeof(timer)); setitimer(ITIMER_REAL, &timer, NULL); sigaction(SIGALRM, &oldact, NULL); #endif LOG(log_info, logtype_dsi, "AFP/TCP session from %s:%u", getip_string((struct sockaddr *)&dsi->client), getip_port((struct sockaddr *)&dsi->client)); } /* send back our pid */ return pid; }
/* * This function tries to register the AFP DNS * SRV service type. */ static void register_stuff(void) { uint port; const struct vol *volume; DSI *dsi; char name[MAXINSTANCENAMELEN+1]; AvahiStringList *strlist = NULL; AvahiStringList *strlist2 = NULL; char tmpname[256]; assert(ctx->client); if (!ctx->group) { if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) { LOG(log_error, logtype_afpd, "Failed to create entry group: %s", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } if (avahi_entry_group_is_empty(ctx->group)) { /* Register our service */ /* Build AFP volumes list */ int i = 0; strlist = avahi_string_list_add_printf(strlist, "sys=waMa=0,adVF=0x100"); for (volume = getvolumes(); volume; volume = volume->v_next) { if (convert_string(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, -1, tmpname, 255) <= 0) { LOG ( log_error, logtype_afpd, "Could not set Zeroconf volume name for TimeMachine"); goto fail; } if (volume->v_flags & AFPVOL_TM) { if (volume->v_uuid) { LOG(log_info, logtype_afpd, "Registering volume '%s' with UUID: '%s' for TimeMachine", volume->v_localname, volume->v_uuid); strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1,adVU=%s", i++, tmpname, volume->v_uuid); } else { LOG(log_warning, logtype_afpd, "Registering volume '%s' for TimeMachine. But UUID is invalid.", volume->v_localname); strlist = avahi_string_list_add_printf(strlist, "dk%u=adVN=%s,adVF=0xa1", i++, tmpname); } } } /* AFP server */ for (dsi = ctx->obj->dsi; dsi; dsi = dsi->next) { port = getip_port((struct sockaddr *)&dsi->server); LOG(log_info, logtype_afpd, "hostname: %s", ctx->obj->options.hostname); if (convert_string(ctx->obj->options.unixcharset, CH_UTF8, ctx->obj->options.hostname, -1, name, MAXINSTANCENAMELEN) <= 0) { LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name: %s", ctx->obj->options.hostname); goto fail; } if ((dsi->bonjourname = strdup(name)) == NULL) { LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name"); goto fail; } LOG(log_info, logtype_afpd, "Registering server '%s' with Bonjour", dsi->bonjourname); if (avahi_entry_group_add_service(ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, dsi->bonjourname, AFP_DNS_SERVICE_TYPE, NULL, NULL, port, NULL) < 0) { LOG(log_error, logtype_afpd, "Failed to add service: %s", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } if (i && avahi_entry_group_add_service_strlst(ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, dsi->bonjourname, ADISK_SERVICE_TYPE, NULL, NULL, 9, /* discard */ strlist) < 0) { LOG(log_error, logtype_afpd, "Failed to add service: %s", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } /* if */ if (ctx->obj->options.mimicmodel) { strlist2 = avahi_string_list_add_printf(strlist2, "model=%s", ctx->obj->options.mimicmodel); if (avahi_entry_group_add_service_strlst(ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, dsi->bonjourname, DEV_INFO_SERVICE_TYPE, NULL, NULL, 0, strlist2) < 0) { LOG(log_error, logtype_afpd, "Failed to add service: %s", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } /* if (config->obj.options.mimicmodel) */ } /* for config*/ if (avahi_entry_group_commit(ctx->group) < 0) { LOG(log_error, logtype_afpd, "Failed to commit entry group: %s", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } /* if avahi_entry_group_is_empty*/ return; fail: time(NULL); // avahi_threaded_poll_quit(ctx->threaded_poll); }