Accept inform response coming from a different port than the request destination port - pysnmp

The following code works when the response source port is 162 but seems to raise an "Unknown SNMP community name encountered" exception when the response source port is dynamic.
Is it related to CommunityData / UdpTransportTarget mapping ? Any ways to accept responses with source port different from the request destination port ?
from pysnmp.hlapi import *
def send_notification(host, community):
errorIndication, errorStatus, errorIndex, varBinds = next(
sendNotification(
SnmpEngine(),
CommunityData(community),
UdpTransportTarget((host, 162)),
ContextData(),
'inform',
NotificationType(
ObjectIdentity('1.3.6.1.4.1.9.90000.1')
).addVarBinds(
('1.3.6.1.4.1.9.90000.1', Integer32(1)),
('1.3.6.1.4.1.9.90000.2', Integer32(2))
)
)
)
if errorIndication:
print(errorIndication)
elif errorStatus:
print('%s: at %s' % (errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
for varBind in varBinds:
print(' = '.join([x.prettyPrint() for x in varBind]))
send_notification('127.0.0.1', 'mycomm')

Related

(Python)What do I do to stop receiving this error? [WinError 10013]An attempt was made to access a socket in a way forbidden by its access permissions

I'm trying to make a python socket client/server chat app, but can't seem to work around this error. I've used netstat -a|findstr 7000 to make sure the port was available, and it was. I don't have any antivirus running besides Windows Security. I also tried it after turning off all firewalls on my computer--have not messed with firewall settings in my router. I'm running both files in Anaconda Powershell Prompt as admin.
Any help is appreciated.
Code for server.py :
from socket import AF_INET, socket, SOCK_STREAM
import threading
BUFSIZ = 1024
FORMAT = 'utf-8'
SERVER = '192.168.1.10'
ADDR = (SERVER, 7000)
server = socket(AF_INET, SOCK_STREAM)
server.bind(ADDR)
sockets = {server}
clients = {}
def accept_incoming_connections():
while True:
client, client_addr = server.accept()
print ("%s:%s has connected." % client_addr)
client.send(bytes("Enter your name and press enter."), FORMAT)
sockets[client] = client_addr
# client_thread = threading.Thread(target=handle_client, args=(client,)).start()
def handle_client(client):
client_name = client.recv(BUFSIZ).decode(FORMAT)
client.send(bytes("Type .exit when you're ready to quit.", FORMAT))
msg = "%s has entered the chat." % client_name
broadcast(bytes(msg, FORMAT))
clients[client] = client_name
while True:
msg = client.recv(BUFSIZ)
if msg == bytes(".exit", FORMAT):
client.send(bytes(".exit", FORMAT))
client.close()
del clients[client]
broadcast(bytes("%s has left the chat." % client_name, FORMAT))
break
else:
broadcast(msg, client_name)
def broadcast(msg, name=""):
for client in clients:
client.send(bytes(name, FORMAT) + msg)
if __name__ == "__main__":
server.listen()
print("Awaiting connection.")
accept_incoming_connections()
Code for client.py :
import socket
import threading
BUFSIZ = 1024
FORMAT = 'utf-8'
SERVER = '192.168.1.10'
ADDR = (SERVER, 7000)
client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_sock.connect(ADDR)
def receive():
msg = client_sock.recv(BUFSIZ).decode(FORMAT)
print(msg)
def send():
msg = input('Enter msg: ')
msg.encode(FORMAT)
client_sock.send(msg)
if msg == ".exit":
client_sock.close()
receive_thread = Thread(target=receive)
receive_thread.start()
EDIT: I fixed it. I set SERVER to 'localhost' and PORT to 9999 for both server and client.

pycom urequests timeouts not working as expected

The standard Pycom urequests library (part of below) does not support user configurable timeouts.
def request(method, url, data=None, json=None, headers={}, stream=None):
try:
proto, dummy, host, path = url.split("/", 3)
except ValueError:
proto, dummy, host = url.split("/", 2)
path = ""
if proto == "http:":
port = 80
elif proto == "https:":
import ussl
port = 443
else:
raise ValueError("Unsupported protocol: " + proto)
if ":" in host:
host, port = host.split(":", 1)
port = int(port)
ai = usocket.getaddrinfo(host, port)
ai = ai[0]
s = usocket.socket(ai[0], ai[1], ai[2])
try:
s.connect(ai[-1])
If the server I'm trying to contact does not respond the code waits at
ai = usocket.getaddrinfo(host, port)
for 30s before exiting with an OSError.
So I changed it using https://github.com/micropython/micropython-lib/pull/263/files as a guide
def request(method, url, data=None, json=None, headers={}, stream=None, timeout=5):
try:
proto, dummy, host, path = url.split("/", 3)
except ValueError:
proto, dummy, host = url.split("/", 2)
path = ""
if proto == "http:":
port = 80
elif proto == "https:":
import ussl
port = 443
else:
raise ValueError("Unsupported protocol: " + proto)
if ":" in host:
host, port = host.split(":", 1)
port = int(port)
ai = usocket.getaddrinfo(host, port)
ai = ai[0]
s = usocket.socket(ai[0], ai[1], ai[2])
if timeout is not None:
assert hasattr(usocket.socket, 'settimeout'), 'Socket does not support timeout'
s.settimeout(timeout)
try:
s.connect(ai[-1])
It did me no good, the damn thing still waits for 30s if there is no server response. If anything I'm worse off because now it also waits for 5s after every server response before returning the data, whereas previously I'd get the data the instant the server responded.
I figure the 30s timeout must be accessible somewhere I just can't figure out where. I'm in a bit over my head here. Can anyone offer some suggestions?

Cant import socket module

i've written the following script on PyCharm IDE:
import socket
import time
sock = socket(socket.AF_INET, socket.SOCK_DGRAM)
hexpacket "00 FF"
ip = raw_input('Target IP: ')
port = input('Port: ')
duration = ('Number of seconds to send packets: ')
timeout = time.time() + duration
sent = 0
while True:
if time.time() > timeout:
break
else:
pass
sock.sendto(hexpacket,(ip,port))
sent = sent +1
print "Send %s packet to %s through ports %s"(send, ip, port)
I get an output from the console of:
TypeError: 'module' object is not callable
I have tried to change the "import socket" statement to either "from socket import socket" and "from socket import *" but both did not help.
I also tried to use "pip install socket" but I get "could not find any downloads that satisfy the requirement socket".
Any idea how do I solve this simple issue? I thought socket is a basic module that comes with every python download.
Thanks for the answers..!
sock = socket(socket.AF_INET, socket.SOCK_DGRAM)
you are using socket object directly it's wrong it's throwing an error
TypeError: 'module' object is not callable
Try this::
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

How to change a socket's IP_MULTICAST_IF

I have a Computer with 5 interfaces: 3 with public IPs and 2 local IPs. I am trying to send "HELLO" to a UDP server, but I would like to change the interface to one of the local IP addresses. I did some research and this is the line I need to add in python:
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("64.195.10.11"))
with 64.195.10.11 being the IP I want to change to
So my python code looks like this:
import socket
MCAST_GRP = '224.0.0.1'
MCAST_PORT = 10222
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("64.195.10.10"))
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))
It works perfectly when I change between my 3 public IP addresses. However, it does not work (packet is not delivered) if I put a local IP in the argument. I am not sure if the script does not send, or the server does not receive. What is happening?
SL
Edit: I am listening using two ways:
import socket
import sys
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 10222))
sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton("224.0.0.1") +
socket.inet_aton("64.195.10.11"))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
while True:
print >>sys.stderr, '\nwaiting to receive message'
data, address = sock.recvfrom(1024)
print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
print >>sys.stderr, data
print >>sys.stderr, 'sending acknowledgement to', address
sock.sendto('ack', address)
and using twisted:
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.application.internet import MulticastServer
class MulticastServerUDP(DatagramProtocol):
def __init__ (self, group, name):
self.group = group
self.name = name
def startProtocol(self):
print '%s Started Listening' % self.group
self.transport.joinGroup(self.group)
def datagramReceived(self, datagram, address):
print "%s Received:"%self.name + repr(datagram) + repr(address)
reactor.listenMulticast(10222, MulticastServerUDP('224.0.0.1', 'SERVER1'), listenMultiple = True)
reactor.run()
In case the server and the client are on the same machine (for testing), maybe you need to set IP_MULTICAST_LOOP option like this (c Code):
int loop_on = 1;
setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop_on, sizeof(loop_on));
In python you can try something like this:
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
Hope this help.
Edit : Adding some trace (From my Linux box)
The code i use is the same as posted by SquallLeohart:
#! /usr/bin/python
import socket
MCAST_GRP = '224.0.0.1'
MCAST_PORT = 10222
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("192.168.1.7"))
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))
And:
#! /usr/bin/python
import socket
import sys
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 10222))
sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton("224.0.0.1") +
socket.inet_aton("192.168.1.7"))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
while True:
print >>sys.stderr, '\nwaiting to receive message'
data, address = sock.recvfrom(1024)
print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
print >>sys.stderr, data
print >>sys.stderr, 'sending acknowledgement to', address
sock.sendto('ack', address)
I got this output :
waiting to receive message
received 5 bytes from ('192.168.1.7', 43761)
HELLO
sending acknowledgement to ('192.168.1.7', 43761)
waiting to receive message
received 5 bytes from ('192.168.1.7', 52326)
HELLO
sending acknowledgement to ('192.168.1.7', 52326)
waiting to receive message
And with tcpdump:
21:01:33.814728 IP localhost.localdomain.34956 > all-systems.mcast.net.10222: UDP, length 5
21:01:35.364605 IP localhost.localdomain.39078 > all-systems.mcast.net.10222: UDP, length 5
21:01:36.228477 IP localhost.localdomain.49926 > all-systems.mcast.net.10222: UDP, length 5
Regards.
The answer: my firewall did not accept udp packet from that RFC1918 IP address.

socket.SO_REUSEADDR: packets received by every vs by newest listener

I got multiple processes listening on the same port subscribed to a multicast address. Packets to this address reach every process. However, when I contact them via unicast, only the newest process gets the message. Where is this behavior documented? How can I change it?
Demo program (Python):
import socket,os,struct,sys
def server():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 4242))
mreq = '\xef\x01\x02\x03' + struct.pack('=I', socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
d = sock.recvfrom(1024)
print('[s' + str(os.getpid()) + '] ' + repr(d))
def client():
caddr = '239.1.2.3'
caddr = '127.0.0.1' # Uncomment this and all servers print
csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
csock.sendto('data from ' + str(os.getpid()), 0, (caddr, 4242))
def main():
if sys.argv[1] == 's':
server()
else:
client()
if __name__ == '__main__':
main()
The MSDN states that the behaviour where multiple sockets are listening to the same port for unicast messages is undefined and that there's no way to know which one will receive the data. I tested a similar setup using C++ and winsock2.2 and had similar results as when I ran your program under python (namely the process-blocking effect).
Here's the MSDN article