mirror of
https://github.com/xcat2/confluent.git
synced 2025-02-19 20:16:04 +00:00
Merge branch 'nodesearch' into osdeploy
This commit is contained in:
commit
54be209f4e
@ -97,6 +97,15 @@ node = {
|
||||
'description': ('Classification of node as server or switch'),
|
||||
'validvalues': ('switch', 'server'),
|
||||
},
|
||||
'api.key': {
|
||||
'description': ('Crypt of api key for self api requests by node'),
|
||||
},
|
||||
'api.armed': {
|
||||
'description': ('Indicates whether an insecure api key request is allowed. '
|
||||
'The format is an expiration time in ISO8601 format. When '
|
||||
'the indicated time passes or the first time a node claims '
|
||||
'the key, key grants will not be allowed.'),
|
||||
},
|
||||
#'id': {
|
||||
# 'description': ('Numeric identifier for node')
|
||||
#},
|
||||
|
87
confluent_server/confluent/credserver.py
Normal file
87
confluent_server/confluent/credserver.py
Normal file
@ -0,0 +1,87 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2019 Lenovo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import confluent.config.configmanager as cfm
|
||||
import datetime
|
||||
import eventlet
|
||||
import eventlet.green.socket as socket
|
||||
import eventlet.greenpool
|
||||
import os
|
||||
|
||||
class CredServer(object):
|
||||
def __init__(self, bindhost='::', bindport=301, ttl=1):
|
||||
self.srv = socket.socket(socket.AF_INET6)
|
||||
self.srv.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
|
||||
self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.srv.bind((bindhost, bindport))
|
||||
self.srv.listen(32)
|
||||
self.gpool = eventlet.greenpool.GreenPool(256)
|
||||
self.cfm = cfm.ConfigManager(None)
|
||||
self.runtime = eventlet.spawn(self.listen)
|
||||
|
||||
def listen(self):
|
||||
while True:
|
||||
client, info = self.srv.accept()
|
||||
if info[1] > 1023:
|
||||
client.close()
|
||||
continue
|
||||
self.gpool.spawn_n(self.handle_client, client)
|
||||
|
||||
def handle_client(self, client):
|
||||
client.send('\xc2\xd1-\xa8\x80\xd8j\xba')
|
||||
tlv = bytearray(client.recv(2))
|
||||
if tlv[0] != 1:
|
||||
client.close()
|
||||
return
|
||||
nodename = client.recv(tlv[1])
|
||||
tlv = bytearray(client.recv(2))
|
||||
apiarmed = self.cfm.get_node_attributes(nodename, 'api.armed')
|
||||
apiarmed = apiarmed.get(nodename, {}).get('api.armed', {}).get('value', None)
|
||||
if not apiarmed:
|
||||
client.close()
|
||||
return
|
||||
now = datetime.datetime.utcnow()
|
||||
expiry = datetime.datetime.strptime(apiarmed, "%Y-%m-%dT%H:%M:%SZ")
|
||||
if now > expiry:
|
||||
self.cfm.set_node_attributes({nodename: {'api.armed': ''}})
|
||||
client.close()
|
||||
return
|
||||
client.send(b'\x02\x20')
|
||||
rttoken = os.urandom(32)
|
||||
client.send(rttoken)
|
||||
client.send('\x00\x00')
|
||||
tlv = bytearray(client.recv(2))
|
||||
if tlv[0] != 3:
|
||||
client.close()
|
||||
return
|
||||
echotoken = client.recv(tlv[1])
|
||||
if echotoken != rttoken:
|
||||
client.close()
|
||||
return
|
||||
tlv = bytearray(client.recv(2))
|
||||
if tlv[0] != 4:
|
||||
client.close()
|
||||
return
|
||||
echotoken = client.recv(tlv[1])
|
||||
self.cfm.set_node_attributes({nodename: {'api.key': echotoken, 'api.armed': ''}})
|
||||
client.recv(2) # drain end of message
|
||||
client.send('\x05\x00') # report success
|
||||
client.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
a = CredServer()
|
||||
while True:
|
||||
eventlet.sleep(86400)
|
@ -65,7 +65,7 @@ import base64
|
||||
import confluent.config.configmanager as cfm
|
||||
import confluent.collective.manager as collective
|
||||
import confluent.discovery.protocols.pxe as pxe
|
||||
#import confluent.discovery.protocols.ssdp as ssdp
|
||||
import confluent.discovery.protocols.ssdp as ssdp
|
||||
import confluent.discovery.protocols.slp as slp
|
||||
import confluent.discovery.handlers.imm as imm
|
||||
import confluent.discovery.handlers.cpstorage as cpstorage
|
||||
@ -877,6 +877,8 @@ def get_nodename_from_chained_smms(cfg, handler, info):
|
||||
nodename = newnodename
|
||||
return nodename
|
||||
|
||||
def get_node_by_uuid(uuid):
|
||||
return nodes_by_uuid.get(uuid, None)
|
||||
|
||||
def get_nodename_from_enclosures(cfg, info):
|
||||
nodename = None
|
||||
@ -1238,8 +1240,7 @@ def start_detection():
|
||||
if rechecker is None:
|
||||
rechecktime = util.monotonic_time() + 900
|
||||
rechecker = eventlet.spawn_after(900, _periodic_recheck, cfg)
|
||||
|
||||
# eventlet.spawn_n(ssdp.snoop, safe_detected)
|
||||
eventlet.spawn_n(ssdp.snoop, None, None, ssdp, get_node_by_uuid)
|
||||
|
||||
def stop_autosense():
|
||||
for watcher in list(autosensors):
|
||||
|
@ -30,9 +30,11 @@
|
||||
|
||||
import confluent.neighutil as neighutil
|
||||
import confluent.util as util
|
||||
import confluent.log as log
|
||||
import eventlet.green.select as select
|
||||
import eventlet.green.socket as socket
|
||||
import struct
|
||||
import traceback
|
||||
|
||||
mcastv4addr = '239.255.255.250'
|
||||
mcastv6addr = 'ff02::c'
|
||||
@ -51,7 +53,7 @@ def scan(services, target=None):
|
||||
yield rply
|
||||
|
||||
|
||||
def snoop(handler, byehandler=None):
|
||||
def snoop(handler, byehandler=None, protocol=None, uuidlookup=None):
|
||||
"""Watch for SSDP notify messages
|
||||
|
||||
The handler shall be called on any service coming online.
|
||||
@ -67,6 +69,7 @@ def snoop(handler, byehandler=None):
|
||||
# Normally, I like using v6/v4 agnostic socket. However, since we are
|
||||
# dabbling in multicast wizardry here, such sockets can cause big problems,
|
||||
# so we will have two distinct sockets
|
||||
tracelog = log.Logger('trace')
|
||||
known_peers = set([])
|
||||
net6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
net6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
|
||||
@ -90,50 +93,73 @@ def snoop(handler, byehandler=None):
|
||||
net6.bind(('', 1900))
|
||||
peerbymacaddress = {}
|
||||
while True:
|
||||
newmacs = set([])
|
||||
machandlers = {}
|
||||
r, _, _ = select.select((net4, net6), (), (), 60)
|
||||
neighutil.update_neigh()
|
||||
while r:
|
||||
for s in r:
|
||||
(rsp, peer) = s.recvfrom(9000)
|
||||
rsp = rsp.split('\r\n')
|
||||
method, _, _ = rsp[0].split(' ', 2)
|
||||
if method == 'NOTIFY':
|
||||
ip = peer[0].partition('%')[0]
|
||||
if ip not in neighutil.neightable:
|
||||
continue
|
||||
if peer in known_peers:
|
||||
continue
|
||||
mac = neighutil.neightable[ip]
|
||||
known_peers.add(peer)
|
||||
newmacs.add(mac)
|
||||
if mac in peerbymacaddress:
|
||||
peerbymacaddress[mac]['peers'].append(peer)
|
||||
else:
|
||||
peerbymacaddress[mac] = {
|
||||
'hwaddr': mac,
|
||||
'peers': [peer],
|
||||
}
|
||||
peerdata = peerbymacaddress[mac]
|
||||
try:
|
||||
newmacs = set([])
|
||||
machandlers = {}
|
||||
r, _, _ = select.select((net4, net6), (), (), 60)
|
||||
neighutil.update_neigh()
|
||||
while r:
|
||||
for s in r:
|
||||
(rsp, peer) = s.recvfrom(9000)
|
||||
rsp = rsp.split('\r\n')
|
||||
method, _, _ = rsp[0].split(' ', 2)
|
||||
if method == 'NOTIFY':
|
||||
ip = peer[0].partition('%')[0]
|
||||
if ip not in neighutil.neightable:
|
||||
continue
|
||||
if peer in known_peers:
|
||||
continue
|
||||
mac = neighutil.neightable[ip]
|
||||
known_peers.add(peer)
|
||||
newmacs.add(mac)
|
||||
if mac in peerbymacaddress:
|
||||
peerbymacaddress[mac]['peers'].append(peer)
|
||||
else:
|
||||
peerbymacaddress[mac] = {
|
||||
'hwaddr': mac,
|
||||
'peers': [peer],
|
||||
}
|
||||
peerdata = peerbymacaddress[mac]
|
||||
for headline in rsp[1:]:
|
||||
if not headline:
|
||||
continue
|
||||
header, _, value = headline.partition(':')
|
||||
header = header.strip()
|
||||
value = value.strip()
|
||||
if header == 'NT':
|
||||
peerdata['service'] = value
|
||||
elif header == 'NTS':
|
||||
if value == 'ssdp:byebye':
|
||||
machandlers[mac] = byehandler
|
||||
elif value == 'ssdp:alive':
|
||||
machandlers[mac] = None # handler
|
||||
elif method == 'M-SEARCH':
|
||||
if not uuidlookup:
|
||||
continue
|
||||
#ip = peer[0].partition('%')[0]
|
||||
for headline in rsp[1:]:
|
||||
if not headline:
|
||||
continue
|
||||
header, _, value = headline.partition(':')
|
||||
header = header.strip()
|
||||
value = value.strip()
|
||||
if header == 'NT':
|
||||
peerdata['service'] = value
|
||||
elif header == 'NTS':
|
||||
if value == 'ssdp:byebye':
|
||||
machandlers[mac] = byehandler
|
||||
elif value == 'ssdp:alive':
|
||||
machandlers[mac] = handler
|
||||
r, _, _ = select.select((net4, net6), (), (), 0.1)
|
||||
for mac in newmacs:
|
||||
thehandler = machandlers.get(mac, None)
|
||||
if thehandler:
|
||||
thehandler(peerbymacaddress[mac])
|
||||
headline = headline.partition(':')
|
||||
if len(headline) < 3:
|
||||
continue
|
||||
if headline[0] == 'ST' and headline[-1].startswith(' urn:xcat.org:service:confluent:'):
|
||||
for query in headline[-1].split('/'):
|
||||
if query.startswith('uuid='):
|
||||
curruuid = query.split('=', 1)[1].lower()
|
||||
node = uuidlookup(curruuid)
|
||||
if not node:
|
||||
break
|
||||
reply = 'HTTP/1.1 200 OK\r\nNODENAME: {0}'.format(node)
|
||||
s.sendto(reply, peer)
|
||||
r, _, _ = select.select((net4, net6), (), (), 0.2)
|
||||
for mac in newmacs:
|
||||
thehandler = machandlers.get(mac, None)
|
||||
if thehandler:
|
||||
thehandler(peerbymacaddress[mac])
|
||||
except Exception:
|
||||
tracelog.log(traceback.format_exc(), ltype=log.DataTypes.event,
|
||||
event=log.Events.stacktrace)
|
||||
|
||||
|
||||
def _find_service(service, target):
|
||||
|
129
misc/clortho.c
129
misc/clortho.c
@ -2,84 +2,125 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <crypt.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define OUI_ETHERTYPE 0x88b7
|
||||
#define MAXPACKET 1024
|
||||
#define CHDR "\xa4\x8c\xdb\x30\x01"
|
||||
|
||||
int get_interface_index(int sock, char *interface) {
|
||||
struct ifreq req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
strncpy(req.ifr_name, interface, IFNAMSIZ);
|
||||
if (ioctl(sock, SIOCGIFINDEX, &req) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return req.ifr_ifindex;
|
||||
}
|
||||
static const char cryptalpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
|
||||
|
||||
unsigned char* genpasswd() {
|
||||
unsigned char* genpasswd(int len) {
|
||||
unsigned char * passwd;
|
||||
int urandom;
|
||||
passwd = calloc(33, sizeof(char));
|
||||
passwd = calloc(len + 1, sizeof(char));
|
||||
urandom = open("/dev/urandom", O_RDONLY);
|
||||
read(urandom, passwd, 32);
|
||||
read(urandom, passwd, len);
|
||||
close(urandom);
|
||||
for (urandom = 0; urandom < 32; urandom++) {
|
||||
passwd[urandom] = 0x30 + (passwd[urandom] >> 2);
|
||||
for (urandom = 0; urandom < len; urandom++) {
|
||||
passwd[urandom] = cryptalpha[passwd[urandom] >> 2];
|
||||
}
|
||||
return passwd;
|
||||
|
||||
}
|
||||
|
||||
int parse_macaddr(char* macaddr) {
|
||||
unsigned char *curr;
|
||||
unsigned char idx;
|
||||
curr = strtok(macaddr, ":-");
|
||||
idx = 0;
|
||||
|
||||
while (curr != NULL) {
|
||||
macaddr[idx++] = strtoul(curr, NULL, 16);
|
||||
curr = strtok(NULL, ":-");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int sock;
|
||||
int iface;
|
||||
unsigned char currlen, currtype;
|
||||
unsigned char* passwd;
|
||||
unsigned char* cryptedpass;
|
||||
unsigned char* macaddr;
|
||||
|
||||
struct timeval timeout;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *addrs;
|
||||
struct addrinfo *curr;
|
||||
struct sockaddr_in net4bind;
|
||||
struct sockaddr_in net6bind;
|
||||
unsigned char buffer[MAXPACKET];
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
memset(&net4bind, 0, sizeof(struct sockaddr_in));
|
||||
memset(&net6bind, 0, sizeof(struct sockaddr_in));
|
||||
memset(&buffer, 0, MAXPACKET);
|
||||
memset(&timeout, 0, sizeof(struct timeval));
|
||||
timeout.tv_sec = 10;
|
||||
net4bind.sin_port = htons(302);
|
||||
net6bind.sin_port = htons(302);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
passwd = genpasswd();
|
||||
passwd = genpasswd(32);
|
||||
memset(buffer, 0, MAXPACKET);
|
||||
strncpy(buffer, "$5$", 3);
|
||||
cryptedpass = genpasswd(8);
|
||||
strncpy(buffer + 3, cryptedpass, 8);
|
||||
free(cryptedpass);
|
||||
cryptedpass = crypt(passwd, buffer);
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Missing interface name and target MAC\n");
|
||||
fprintf(stderr, "Missing node name and manager\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("%s\n", argv[2]);
|
||||
parse_macaddr(argv[2]);
|
||||
printf("%s\n", argv[2]);
|
||||
sock = socket(AF_PACKET, SOCK_DGRAM, htons(OUI_ETHERTYPE));
|
||||
if (sock < 0) {
|
||||
fprintf(stderr, "Unable to open socket (run as root?)\n");
|
||||
sock = getaddrinfo(argv[2], "301", &hints, &addrs);
|
||||
if (sock != 0) {
|
||||
fprintf(stderr, "Error trying to resolve %s\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
iface = get_interface_index(sock, argv[1]);
|
||||
if (iface < 0) {
|
||||
fprintf(stderr, "Unable to find specified interface '%s'\n", argv[1]);
|
||||
for (curr = addrs; curr != NULL; curr = curr->ai_next) {
|
||||
sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
|
||||
if (sock < 0) continue;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
|
||||
if (curr->ai_family == AF_INET) {
|
||||
bind(sock, (struct sockaddr*)&net4bind, sizeof(struct sockaddr_in));
|
||||
} else if (curr->ai_family == AF_INET6) {
|
||||
bind(sock, (struct sockaddr*)&net6bind, sizeof(struct sockaddr_in6));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (connect(sock, curr->ai_addr, curr->ai_addrlen) == 0) break;
|
||||
}
|
||||
if (curr == NULL) {
|
||||
fprintf(stderr, "Unable to reach %s\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
freeaddrinfo(addrs);
|
||||
read(sock, buffer, 8);
|
||||
if (memcmp(buffer, "\xc2\xd1-\xa8\x80\xd8j\xba", 8) != 0) {
|
||||
fprintf(stderr, "Unrecognized server\n");
|
||||
exit(1);
|
||||
}
|
||||
dprintf(sock, "\x01%c%s", strlen(argv[1]), argv[1]);
|
||||
write(sock, "\x00\x00", 2);
|
||||
memset(buffer, 0, MAXPACKET);
|
||||
read(sock, buffer, 2);
|
||||
while (buffer[0] != 255) {
|
||||
currtype = buffer[0];
|
||||
currlen = buffer[1];
|
||||
memset(buffer, 0, MAXPACKET);
|
||||
if (currlen) {
|
||||
read(sock, buffer, currlen); // Max is 255, well under MAX_PACKET
|
||||
}
|
||||
if (currtype == 2) {
|
||||
dprintf(sock, "\x03%c", currlen);
|
||||
write(sock, buffer, currlen);
|
||||
dprintf(sock, "\x04%c%s", strlen(cryptedpass), cryptedpass);
|
||||
write(sock, "\x00\x00", 2);
|
||||
} else if (currtype == 5) {
|
||||
printf(passwd);
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
buffer[0] = 255;
|
||||
read(sock, buffer, 2);
|
||||
}
|
||||
fprintf(stderr, "Password was not accepted\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,11 @@ int main(int argc, char* argv[]) {
|
||||
struct sockaddr_in6 addr, dst;
|
||||
struct sockaddr_in addr4, dst4;
|
||||
char msg[1024];
|
||||
char *nodenameidx;
|
||||
char nodename[1024];
|
||||
char lastnodename[1024];
|
||||
char lastmsg[1024];
|
||||
char last6msg[1024];
|
||||
int ifidx, offset;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
@ -80,6 +84,10 @@ int main(int argc, char* argv[]) {
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
memset(&dst4, 0, sizeof(dst4));
|
||||
memset(nodename, 0, 1024);
|
||||
memset(lastnodename, 0, 1024);
|
||||
memset(lastmsg, 0, 1024);
|
||||
memset(last6msg, 0, 1024);
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_addr = in6addr_any;
|
||||
addr.sin6_port = htons(190);
|
||||
@ -141,20 +149,52 @@ int main(int argc, char* argv[]) {
|
||||
if (ifidx == -1) perror("Unable to select");
|
||||
if (ifidx) {
|
||||
if (FD_ISSET(n4, &rfds)) {
|
||||
recvfrom(n4, msg, 1024, 0, (struct sockaddr *)&dst4, &dst4size);
|
||||
memset(msg, 0, 1024);
|
||||
/* Deny packet access to the last 24 bytes to assure null */
|
||||
recvfrom(n4, msg, 1000, 0, (struct sockaddr *)&dst4, &dst4size);
|
||||
if (nodenameidx = strstr(msg, "NODENAME: ")) {
|
||||
nodenameidx += 10;
|
||||
strncpy(nodename, nodenameidx, 1024);
|
||||
nodenameidx = strstr(nodenameidx, "\r");
|
||||
if (nodenameidx) { nodenameidx[0] = 0; }
|
||||
if (strncmp(lastnodename, nodename, 1024) != 0) {
|
||||
printf("NODENAME: %s\n", nodename);
|
||||
strncpy(lastnodename, nodename, 1024);
|
||||
}
|
||||
}
|
||||
memset(msg, 0, 1024);
|
||||
inet_ntop(dst4.sin_family, &dst4.sin_addr, msg, dst4size);
|
||||
/* Take measure from printing out the same ip twice in a row */
|
||||
if (strncmp(lastmsg, msg, 1024) != 0) {
|
||||
printf("%s\n", msg);
|
||||
sendto(n4, "PING", 4, 0, (const struct sockaddr *)&dst4, dst4size);
|
||||
printf("MANAGER: %s\n", msg);
|
||||
strncpy(lastmsg, msg, 1024);
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(ns, &rfds)) {
|
||||
recvfrom(ns, msg, 1024, 0, (struct sockaddr *)&dst, &dstsize);
|
||||
memset(msg, 0, 1024);
|
||||
/* Deny packet access to the last 24 bytes to assure null */
|
||||
recvfrom(ns, msg, 1000, 0, (struct sockaddr *)&dst, &dstsize);
|
||||
if (nodenameidx = strstr(msg, "NODENAME: ")) {
|
||||
nodenameidx += 10;
|
||||
strncpy(nodename, nodenameidx, 1024);
|
||||
nodenameidx = strstr(nodenameidx, "\r");
|
||||
if (nodenameidx) { nodenameidx[0] = 0; }
|
||||
if (strncmp(lastnodename, nodename, 1024) != 0) {
|
||||
printf("NODENAME: %s\n", nodename);
|
||||
strncpy(lastnodename, nodename, 1024);
|
||||
}
|
||||
}
|
||||
memset(msg, 0, 1024);
|
||||
inet_ntop(dst.sin6_family, &dst.sin6_addr, msg, dstsize);
|
||||
if (strncmp(lastmsg, msg, 1024) != 0) {
|
||||
printf("%s\n", msg);
|
||||
strncpy(lastmsg, msg, 1024);
|
||||
if (strncmp(last6msg, msg, 1024) != 0) {
|
||||
sendto(ns, "PING", 4, 0, (const struct sockaddr *)&dst, dstsize);
|
||||
printf("MANAGER: %s", msg);
|
||||
if (strncmp(msg, "fe80::", 6) == 0) {
|
||||
printf("%%%u", dst.sin6_scope_id);
|
||||
}
|
||||
printf("\n");
|
||||
strncpy(last6msg, msg, 1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user