setSockOptIPv6 implements the linux setsockopt(2) when the level is SOL_IPV6.
(t *kernel.Task, ep commonEndpoint, name int, optVal []byte)
| 2426 | |
| 2427 | // setSockOptIPv6 implements the linux setsockopt(2) when the level is SOL_IPV6. |
| 2428 | func (s *sock) setSockOptIPv6(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *syserr.Error { |
| 2429 | if _, ok := ep.(tcpip.Endpoint); !ok { |
| 2430 | log.Warningf("SOL_IPV6 options not supported on endpoints other than tcpip.Endpoint: option = %d", name) |
| 2431 | return syserr.ErrUnknownProtocolOption |
| 2432 | } |
| 2433 | |
| 2434 | family, _, _ := s.Type() |
| 2435 | if family != linux.AF_INET6 { |
| 2436 | return syserr.ErrUnknownProtocolOption |
| 2437 | } |
| 2438 | |
| 2439 | switch name { |
| 2440 | case linux.IPV6_CHECKSUM: |
| 2441 | if len(optVal) < sizeOfInt32 { |
| 2442 | return syserr.ErrInvalidArgument |
| 2443 | } |
| 2444 | |
| 2445 | // int may not be 32-bits so we cast the uint32 to an int32 before casting |
| 2446 | // to an int. |
| 2447 | return syserr.TranslateNetstackError(ep.SetSockOptInt(tcpip.IPv6Checksum, int(int32(hostarch.ByteOrder.Uint32(optVal))))) |
| 2448 | |
| 2449 | case linux.IPV6_V6ONLY: |
| 2450 | if len(optVal) < sizeOfInt32 { |
| 2451 | return syserr.ErrInvalidArgument |
| 2452 | } |
| 2453 | |
| 2454 | if socket.IsTCP(s) && tcp.EndpointState(ep.State()) != tcp.StateInitial { |
| 2455 | return syserr.ErrInvalidEndpointState |
| 2456 | } else if socket.IsUDP(s) && transport.DatagramEndpointState(ep.State()) != transport.DatagramEndpointStateInitial { |
| 2457 | return syserr.ErrInvalidEndpointState |
| 2458 | } |
| 2459 | |
| 2460 | v := hostarch.ByteOrder.Uint32(optVal) |
| 2461 | ep.SocketOptions().SetV6Only(v != 0) |
| 2462 | return nil |
| 2463 | |
| 2464 | case linux.IPV6_ADD_MEMBERSHIP: |
| 2465 | req, err := copyInMulticastV6Request(optVal) |
| 2466 | if err != nil { |
| 2467 | return err |
| 2468 | } |
| 2469 | |
| 2470 | return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.AddMembershipOption{ |
| 2471 | NIC: tcpip.NICID(req.InterfaceIndex), |
| 2472 | MulticastAddr: tcpip.AddrFrom16(req.MulticastAddr), |
| 2473 | })) |
| 2474 | |
| 2475 | case linux.IPV6_DROP_MEMBERSHIP: |
| 2476 | req, err := copyInMulticastV6Request(optVal) |
| 2477 | if err != nil { |
| 2478 | return err |
| 2479 | } |
| 2480 | |
| 2481 | return syserr.TranslateNetstackError(ep.SetSockOpt(&tcpip.RemoveMembershipOption{ |
| 2482 | NIC: tcpip.NICID(req.InterfaceIndex), |
| 2483 | MulticastAddr: tcpip.AddrFrom16(req.MulticastAddr), |
| 2484 | })) |
| 2485 |
no test coverage detected